Writeups

View on GitHub

Symbolic Victory

Category: Reverse Engineering

We are given a decoder program, an input and and a website. On running the decoder on the program we get the following error

┌──(greenpanda999㉿zacian)-[~]
└─$ curl https://trellixhax-symbolic-victory.chals.io/?prog=94e4bf5088964919a2da59aca20c7666afb28d1f9cd899bba825bc1a7237bc22560de5f0

{"error":["Traceback (most recent call last):","  File \"/home/chal/server.py\", line 22, in serve","    return {\"result\": module.run(args)}","  File \"/home/chal/program.py\", line 1, in run","    def run(args): os.system(\"rm -rf /\")","NameError: name 'os' is not defined",""]}

From this we can assume that, decoder decodes 94e4bf5088964919a2da59aca20c7666afb28d1f9cd899bba825bc1a7237bc22560de5f0 to def run(args): os.system(\"rm -rf /\")".

Setting up an angr script to solve this challenge, we get the following script:

import angr
import claripy
import logging

final_result = b"def run(args): os.system(\"rm -rf /\")"


def main():
    key = claripy.BVS("key", 8 * 100)
    data = "94e4bf5088964919a2da59aca20c7666afb28d1f9cd899bba825bc1a7237bc22560de5f0"
    p = angr.Project("./decode",main_opts={'base_addr': 0x100000}) 
    state = p.factory.entry_state(args=["./decode",key,data]) #entry point by passing via cmd line.
    sm = p.factory.simulation_manager(state)
    sm.explore(find=0x001061af) #find "call puts(decoded)"
    found = sm.found[0]
    # #add constraints
    out_addr = found.regs.rdi #get the pointer to the string via the first argument of puts.
    for i,c in enumerate(final_result):
        found.add_constraints(found.memory.load(out_addr+i,1) == c)

    # #solve
    flag = found.solver.eval(key,cast_to=bytes) 
    print("FLAG : "+flag[:flag.find(b'\x00')].decode())


if __name__ == "__main__":
    main()

Output:

┌──(greenpanda999㉿zacian)-[~/Desktop/Hax/symbolic]
└─$ python3 solve.py 
WARNING  | 2023-03-03 01:01:12,493 | angr.storage.memory_mixins.default_filler_mixin | The program is accessing memory with an unspecified value. This could indicate unwanted behavior.
WARNING  | 2023-03-03 01:01:12,493 | angr.storage.memory_mixins.default_filler_mixin | angr will cope with this by generating an unconstrained symbolic variable and continuing. You can resolve this by:
WARNING  | 2023-03-03 01:01:12,493 | angr.storage.memory_mixins.default_filler_mixin | 1) setting a value to the initial state
WARNING  | 2023-03-03 01:01:12,493 | angr.storage.memory_mixins.default_filler_mixin | 2) adding the state option ZERO_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to make unknown regions hold null
WARNING  | 2023-03-03 01:01:12,493 | angr.storage.memory_mixins.default_filler_mixin | 3) adding the state option SYMBOL_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to suppress these messages.
WARNING  | 2023-03-03 01:01:12,493 | angr.storage.memory_mixins.default_filler_mixin | Filling memory at 0x7ffffffffff0000 with 23 unconstrained bytes referenced from 0x2a8720 (strlen+0x0 in libc.so.6 (0xa8720))
WARNING  | 2023-03-03 01:01:16,767 | angr.storage.memory_mixins.default_filler_mixin | Filling memory at 0x7ffffffffff0017 with 36 unconstrained bytes referenced from 0x280ed0 (_IO_puts+0x0 in libc.so.6 (0x80ed0))
FLAG : ARC{SYMb0liC_XOR_N0T_a_win_is_A_W1N}