Skip to content

Instantly share code, notes, and snippets.

@d0now
Created November 9, 2022 18:08
Show Gist options
  • Select an option

  • Save d0now/c7e5fc8ada627f4e0862cb13624f17ea to your computer and use it in GitHub Desktop.

Select an option

Save d0now/c7e5fc8ada627f4e0862cb13624f17ea to your computer and use it in GitHub Desktop.
2022 snyk.io fetch the flag - smart fridge solve
  1. you can get server binary using: curl --path-as-is http://[SERVER]/docs/../../../../../../../proc/self/exe
  2. and you need to reverse-engineering the function Service::checkFlag
  3. I used binary ninja for automation and it was quite easy for me.
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