Procedure followed is to boot the machine by a cdrom in single user mode, mount
the root file system and then to edit /etc/shadow file. One of my Sys Admin
friend wanted to know if there was a way to do this without cdrom and hence
this exercise of booting the machine with kmdb.
First thing I did was to boot the machine in single user mode with kmdb loaded:
ok boot kmdb -s
Resetting ...
Sun Serverblade1 (UltraSPARC-IIe 650MHz), No Keyboard
Copyright 1998-2003 Sun Microsystems, Inc. All rights reserved.
OpenBoot 4.11.3, 1024 MB memory installed, Serial #52785242.
Ethernet address 0:3:ba:4d:3:74, Host ID: 8325705a.
Rebooting with command: boot kmdb -s
Boot device: /pci@1f,0/ide@d/disk@0,0:a File and args: kmdb -s
Loading kmdb...
SunOS Release 5.10 Version Generic_141444-09 64-bit
Copyright 1983-2009 Sun Microsystems, Inc. All rights reserved.
Use is subject to license terms.
WARNING: todblade: kernel debugger detected: hardware watchdog disabled
Booting to milestone "milestone/single-user:default".
Hostname: solarisbox
As soon as I got the hostname displayed on the console, I sent a break and
dropped into kmdb prompt.
cli>break -y s3
s3: Break sent.
cli>console -f s3
[Connected with input enabled on fru S3]
Escape Sequence is '#.'
I then added a break point at exec_common to trace the exec of sulogin process.
[0]> exec_common+0x16c:b
[0]> :c
kmdb: stop at exec_common+0x16c
kmdb: target stopped at:
exec_common+0x16c: orcc %g0, %o0, %i3
[0]> $C
000002a100728ff1 exec_common+0x16c(40e0c, 0, cdf18, 1813070, 0, 0)
000002a100729231 exece+0x10(40e0c, fd87bdf0, cdf18, b9fa8, 1010101, 80808080)
000002a1007292e1 syscall_trap32+0xcc(40e0c, fd87bdf0, cdf18, b9fa8, 1010101,
80808080)
[0]> 000002a100729231+0x7c7::print struct pathname
{
pn_buf = 0x30002b20080 "/sbin/sh"
pn_path = 0x30002b20080 "/sbin/sh"
pn_pathlen = 0x8
pn_bufsize = 0x400
}
[0]>
Above doesn't look like the one we are interested in. I put a break point at
exec_common+0x16c because, the pathname passed in from userland is pulled into
kernel land by pn_get at exec_common+0x16c. Look at following dis code.
[0]> exec_common+0x16c::dis
exec_common+0x144: ld [%g7 + 0x124], %l4
exec_common+0x148: st %l4, [%fp + 0x7eb]
exec_common+0x14c: call +0x8f724 <sigorset>
exec_common+0x150: add %g1, 0x3a8, %o1
exec_common+0x154: call -0xa6df0 <mutex_exit>
exec_common+0x158: ldx [%l1 + 0x10], %o0
exec_common+0x15c: add %fp, 0x7c7, %o2
exec_common+0x160: mov %i0, %o0
exec_common+0x164: call +0x4c130 <pn_get>
exec_common+0x168: mov %i4, %o1
exec_common+0x16c: orcc %g0, %o0, %i3
exec_common+0x170: bne,pn %icc, +0x6d8 <exec_common+0x848>
exec_common+0x174: add %fp, 0x7a7, %l7
exec_common+0x178: call +0x4c044 <pn_alloc>
exec_common+0x17c: add %fp, 0x7a7, %o0
exec_common+0x180: add %fp, 0x7c7, %o0
exec_common+0x184: add %fp, 0x7ef, %o3
exec_common+0x188: add %fp, 0x7f7, %o4
exec_common+0x18c: mov %l7, %o1
exec_common+0x190: call +0x30008 <lookuppn>
exec_common+0x194: mov 0x1, %o2
[0]>
I had to now step through exec_common+0x16c as shown below. I ignored around
30 exec_common calls and blindly continued as nothing was interesting and
relevant.
I was looking for "Requesting System Maintenance Mode" message to be displayed
on console. This message is displayed while sulogin process is created:
http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/svc/startd/fork.c#221
[0]> :c
Requesting System Maikmdb: stop at exec_common+0x16c
kmdb: target stopped at:
exec_common+0x16c: orcc %g0, %o0, %i3
Part of "Requesting System Maintenance Mode" message is displayed, this should
be the process of our interest.
[0]> $C
000002a100758ff1 exec_common+0x16c(38f3c, 0, ffbfff18, 1813070, 0, 0)
000002a100759231 exece+0x10(38f3c, fd07be58, ffbfff18, 7cf28, 0, ff2303a8)
000002a1007592e1 syscall_trap32+0xcc(38f3c, fd07be58, ffbfff18, 7cf28, 0,
ff2303a8)
[0]> 000002a100759231+0x7c7::print struct pathname
{
pn_buf = 0x30002b1e480 "/sbin/sulogin"
pn_path = 0x30002b1e480 "/sbin/sulogin"
pn_pathlen = 0xd
pn_bufsize = 0x400
}
Yes, indeed this is the process of our interest. sulogin will later read in
/etc/shadow file for root entry. It is better to track all UFS file systems
read function from now on and to look out for /etc/shadow file.
[0]> ufs_read+8:b
[0]> :c
ntenkmdb: stop at ufs`ufs_read+8
kmdb: target stopped at:
ufs`ufs_read+8: clr %l0
I stepped through uninteresting files. After reading /etc/default/login and
/etc/nsswitch.conf file, sulogin opens /etc/shadow file.
[0]> $c
ufs`ufs_read+8(30003c2ca00, 2a100759a10, 0, 300004d1d98, 0, ff3f6ae8)
fop_read+0x20(30003c2ca00, 2a100759a10, 0, 300004d1d98, 0, 135b98c)
read+0x274(101, 0, 30001d3da48, 400, 2001, 0)
syscall_trap32+0xcc(101, 261a0, 400, 0, ff3f4910, 821)
[0]> 30003c2ca00::print vnode_t v_path
v_path = 0x30001864908 "/etc/shadow"
[0]> ::pgrep sulogin
S PID PPID PGID SID UID FLAGS ADDR NAME
R 139 7 139 139 0 0x4a004000 00000300002df858 sulogin
[0]> 00000300002df858::pfiles
FD TYPE VNODE INFO
0 CHR 000003000280edc0 /devices/pseudo/cn@0:console
1 CHR 000003000280edc0 /devices/pseudo/cn@0:console
2 CHR 000003000280edc0 /devices/pseudo/cn@0:console
3 CHR 0000030003c2d200 /devices/pseudo/sysmsg@0:sysmsg
256 REG 0000030003c2ca00 /etc/shadow
257 REG 0000030003c2ca00 /etc/shadow
I then put a break point at uiomove+8. Once the data is read into memory, UFS
uses uiomove to copy read in data from kernel land to user land.
[0]> uiomove+8:b
[0]> :c
kmdb: stop at uiomove+8
kmdb: target stopped at:
uiomove+8: be,pn %xcc, +0x13c <uiomove+0x144>
[0]> $c
uiomove+8(fffffa003a6e0000, 15f, 0, 2a100759a10, fffffa003a6e0000, 15f)
vpm_data_copy+0x100(30003c2ca00, 0, 15f, 2a100759a10, 109a358, 15f)
ufs`rdip+0x468(0, 1fff, ffffffffffffe000, 186a060, 30003c6b720, 18ffd58)
ufs`ufs_read+0x208(30003c6b800, 2a100759a10, 0, 300004d1d98, 30003c6b800,
300000a1a80)
fop_read+0x20(30003c2ca00, 2a100759a10, 0, 300004d1d98, 0, 135b98c)
read+0x274(101, 0, 30001d3da48, 400, 2001, 0)
syscall_trap32+0xcc(101, 261a0, 400, 0, ff3f4910, 821)
[0]> fffffa003a6e0000 \s
0xfffffa003a6e0000: root:wqXY4dQaZCTfs:6445::::::
daemon:NP:6445::::::
bin:NP:6445::::::
sys:NP:6445::::::
adm:NP:6445::::::
lp:NP:6445::::::
uucp:NP:6445::::::
nuucp:NP:6445::::::
smmsp:NP:6445::::::
listen:*LK*:::::::
gdm:*LK*:::::::
webservd:*LK*:::::::
postgres:NP:::::::
svctag:*LK*:6445::::::
nobody:*LK*:6445::::::
noaccess:*LK*:6445::::::
nobody4:*LK*:6445::::::
[0]>
The idea is to modify read in data in memory and have encrypted password for
root removed.
[0]> fffffa003a6e0005 \v 3a
0xfffffa003a6e0005: 0x77 = 0x3a
[0]> fffffa003a6e0006 \v 36
0xfffffa003a6e0006: 0x71 = 0x36
[0]> fffffa003a6e0007 \v 34
0xfffffa003a6e0007: 0x58 = 0x34
[0]> fffffa003a6e0008 \v 34
0xfffffa003a6e0008: 0x59 = 0x34
[0]> fffffa003a6e0009 \v 35
0xfffffa003a6e0009: 0x34 = 0x35
[0]> fffffa003a6e000a \v 3a
0xfffffa003a6e000a: 0x64 = 0x3a
[0]> fffffa003a6e000b \v 3a
0xfffffa003a6e000b: 0x51 = 0x3a
[0]> fffffa003a6e000c \v 3a
0xfffffa003a6e000c: 0x61 = 0x3a
[0]> fffffa003a6e000d \v 3a
0xfffffa003a6e000d: 0x5a = 0x3a
[0]> fffffa003a6e000e \v 3a
0xfffffa003a6e000e: 0x43 = 0x3a
[0]> fffffa003a6e000f \v 3a
0xfffffa003a6e000f: 0x54 = 0x3a
[0]> fffffa003a6e0010 \v d
0xfffffa003a6e0010: 0x66 = 0xd
[0]> fffffa003a6e0000 \s
s:14761:::::: root::6445::::::
daemon:NP:6445::::::
bin:NP:6445::::::
sys:NP:6445::::::
adm:NP:6445::::::
lp:NP:6445::::::
uucp:NP:6445::::::
nuucp:NP:6445::::::
smmsp:NP:6445::::::
listen:*LK*:::::::
gdm:*LK*:::::::
webservd:*LK*:::::::
postgres:NP:::::::
svctag:*LK*:6445::::::
nobody:*LK*:6445::::::
noaccess:*LK*:6445::::::
nobody4:*LK*:6445::::::
[0]>
Once this was done, I removed all break points and continued boot process. Now
the root entry without password is copied from kernel land to user land.
[0]> :z
[0]> :c
Root password for system maintenance (control-d to bypass):
single-user privilege assigned to /dev/console.
Entering System Maintenance Mode
<root>#
At "Root password" prompt, I had to hit "Enter" key to login.
We can also get to cached file data using Virtual vnode and page structures.
[0]> 30003c6b800::print vnode_t v_pages | ::print page_t p_pagenum
p_pagenum = 0x1f974
[0]> _pagesize::print
0x2000
[0]> 0x1f974 * 0x2000 \s
0x3f2e8000: root:wqXY4dQaZCTfs:6445::::::
daemon:NP:6445::::::
bin:NP:6445::::::
sys:NP:6445::::::
adm:NP:6445::::::
lp:NP:6445::::::
uucp:NP:6445::::::
nuucp:NP:6445::::::
smmsp:NP:6445::::::
listen:*LK*:::::::
gdm:*LK*:::::::
webservd:*LK*:::::::
postgres:NP:::::::
svctag:*LK*:6445::::::
nobody:*LK*:6445::::::
noaccess:*LK*:6445::::::
nobody4:*LK*:6445::::::
[0]>
We could have then gone about modifying addresses from 0x3f2e8005 to 0x3f2e8010
to get the same result.
After logging into the system, dumped the contents of /etc/shadow:
<root># cat /etc/shadow
s:14761:::::::::
daemon:NP:6445::::::
bin:NP:6445::::::
sys:NP:6445::::::
adm:NP:6445::::::
lp:NP:6445::::::
uucp:NP:6445::::::
nuucp:NP:6445::::::
smmsp:NP:6445::::::
listen:*LK*:::::::
gdm:*LK*:::::::
webservd:*LK*:::::::
postgres:NP:::::::
svctag:*LK*:6445::::::
nobody:*LK*:6445::::::
noaccess:*LK*:6445::::::
nobody4:*LK*:6445::::::
Even though cat shows the content of /etc/shadow as modified, this modification
has happened only in cache (kernel memory). Opening /etc/shadow file in vi shows
something like below:
<snip>
root::6445::::::^Ms:14761::::::
daemon:NP:6445::::::
bin:NP:6445::::::
<snip>
Edit the first line and remove "^Ms:14761::::::".
Rebooting the machine now will not prompt for root password until a new password
is set.
No comments:
Post a Comment