We try to compile it but fail, the far step we do only converting it to object file using command “aarch64-linux-gnu-as -o chall.o asm.s” in kali linux aarch64. After getting the object file we use ghidra to decompile it.
Since the algorithm is not too complex, we try reimplement the code in python and then run it to get flag. Actually we try to use ida also but somehow it doesn’t produce the flag. Here is reimplement code in python
Flag : CJ2023{leet_low_level_learner_avoid_large_language_model}
Centifd (500 pts)
Description
-
Solution
Given elf 32 bit and packed with upx new version. Here we used upx-4.0.2-amd64_linux version. After unpacking the binary we try to decompile it using ida. Basically we try to find out where our input processed by doing dynamic analysis with hardware breakpoint. At the end we found that our input processed in address 0x15231 (xored) and then on 0x15233 (substracted) which is on centifd__stub_15
After that there is something like debugger detection with ptrace but we can easily bypass it. Looking at another function after centifd__stub_15 we found that the binary write another binary on memfd then execute it , including our input.
So to dump the binary we can breakpoint on address inside write__system which is fwrite
After that just dump the binary. When we manually dump the binary and then unpack the dumped binary then we found that the binary is “typical”. So the next step is we automate the process for dumping the binary using script below
#!/usr/bin/python3import osimport timestatic_val=[]classSolverEquation(gdb.Command):def__init__ (self):super(SolverEquation, self).__init__ ("solve-equation",gdb.COMMAND_OBSCURE)definvoke (self,arg,from_tty):# for i in range(100):for i inrange(80): counter = i gdb.execute(f"file out/result{counter}.bin") gdb.execute("pie del") gdb.execute("pie b 0x25db") gdb.execute("pie run A") start_mem =parse(gdb.execute("x/wx $esp", to_string=True))[0] length =parse(gdb.execute("x/wx $esp+0x8", to_string=True))[0] gdb.execute(f"dump binary memory out/result{counter}.bin {hex(start_mem)}{hex(start_mem+length)}") os.system(f"out/upx -d out/result{counter}.bin") os.system(f"chmod +x out/result{counter}.bin") time.sleep(1) gdb.execute(f"file out/result{counter}.bin")defparse(f): f = f.split("\n") result = []for i in f: tmp = i.split("\t")for j inrange(1,len(tmp)): result.append(int(tmp[j],16))return resultdefaddr2num(addr):try:returnint(addr)# Python 3except:returnlong(addr)# Python 2SolverEquation()
After that we get the xor value and the subtract value through scripting then reverse it to get the flag. Here is script we used during the competition
#!/usr/bin/python3import osimport timeclassSolverEquation(gdb.Command):def__init__ (self):super(SolverEquation, self).__init__ ("solve-equation",gdb.COMMAND_OBSCURE)definvoke (self,arg,from_tty): xor = [] sub = [] flag = ['C','J','2']for i inrange(41): counter = i gdb.execute(f"file out/result{counter}.bin") gdb.execute("pie del") gdb.execute("pie b 0x15231")# xor gdb.execute("pie run A") ebx =addr2num(gdb.selected_frame().read_register("ebx")) gdb.execute("ni") arch = gdb.selected_frame().architecture() current_pc =addr2num(gdb.selected_frame().read_register("pc")) disa = arch.disassemble(current_pc)[0] tmp =int(disa["asm"].split(",")[-1],16) xor.append(ebx) sub.append(tmp) flag.append(chr(ebx ^ tmp))print(counter, ''.join(flag)) flag.append(chr(112))# error 41 (no substract)for i inrange(42, 81): counter = i gdb.execute(f"file out/result{counter}.bin") gdb.execute("pie del") gdb.execute("pie b 0x15231")# xor gdb.execute("pie run A") ebx =addr2num(gdb.selected_frame().read_register("ebx")) gdb.execute("ni") arch = gdb.selected_frame().architecture() current_pc =addr2num(gdb.selected_frame().read_register("pc")) disa = arch.disassemble(current_pc)[0] tmp =int(disa["asm"].split(",")[-1],16) xor.append(ebx) sub.append(tmp) flag.append(chr(ebx ^ tmp))print(counter, ''.join(flag))defparse(f): f = f.split("\n") result = []for i in f: tmp = i.split("\t")for j inrange(1,len(tmp)): result.append(int(tmp[j],16))return resultdefaddr2num(addr):try:returnint(addr)# Python 3except:returnlong(addr)# Python 2SolverEquation()
We also facing issue during iteration on 41 since it doesn’t have subtract operation (only xor). But we can skip it by changing the range of iteration without 41.
Flag : CJ2023{did_you_know_despite_their_name_centipede_dont_always_have_exactly_100_legs}