Tags: idapython pintool angr 

Rating:

Binary sets up a rwx segement, writes some code there and jumps to it.
Arount 263 functions in the self modifying code. Each function first decrypts the next one and then calls it with the flag and a bool param. Decryption is a single byte xor.

Find pattern in decryption routine and decrypt statically in IDA first, or use pintool to dump all instructions while executing
```python
size_code = 0x2236f

def decrypt_code(start_idx, key, ln):
for i in xrange(ln):
PatchByte(start_idx+i, key^Byte(start_idx+i))

def scan_start(start_idx):
i = start_idx
while Byte(i) != 0x74 or Byte(i+1) != 0x5:
i += 1
if i > size_code:
return (-1, -1, -1)
code_start = i + 7
key = Byte(code_start) ^ 0x55
length = Dword(i+3)
return (code_start, key, length)

start_addr = 0
code_start, key, length = scan_start(start_addr)
print "%x:%x:%x" % (code_start, key, length)
decrypt_code(code_start, key, length)
MakeCode(code_start)
# raw_input()
while code_start > 0 and code_start < size_code:
code_start, key, length = scan_start(code_start)
print "%x:%x:%x" % (code_start, key, length)
if code_start + length > size_code:
break
decrypt_code(code_start, key, length)
MakeCode(code_start)
```

```cpp
#include "pin.H"
#include <fstream>
#include <stdio.h>

using namespace std;

KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool", "o", "pin.out",
"specify output file name");
ofstream outFile;
ADDRINT l, h;

VOID log_ret(CONTEXT *ctx) {
PIN_REGISTER regval, regval1;
PIN_GetContextRegval(ctx, REG_RAX, reinterpret_cast<UINT8 *>(&regval));
PIN_GetContextRegval(ctx, REG_RIP, reinterpret_cast<UINT8 *>(&regval1));
outFile << std::hex << regval1.qword[0] << " : returns " << regval.qword[0]
<< endl;
}

VOID log_call(CONTEXT *ctx) {
PIN_REGISTER regval, regval1;
PIN_GetContextRegval(ctx, REG_RAX, reinterpret_cast<UINT8 *>(&regval));
PIN_GetContextRegval(ctx, REG_RIP, reinterpret_cast<UINT8 *>(&regval1));
outFile << std::hex << regval.qword[0] << " called from "
<< regval1.qword[0] << endl;
}

VOID callback_instruction(INS ins, VOID *v) {

if (INS_IsRet(ins)) {
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)log_ret, IARG_CONTEXT,
IARG_END);
}
if (INS_IsCall(ins)) {
if (INS_IsIndirectBranchOrCall(ins) &&
INS_OperandReg(ins, 0) == REG_RAX)
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)log_call, IARG_CONTEXT,
IARG_END);
}
// outFile << std::hex << INS_Address(ins) << " : " << INS_Disassemble(ins)
// << endl;
}

VOID fini(INT32 code, VOID *v) { outFile.close(); }

int main(int argc, char *argv[]) {
if (PIN_Init(argc, argv)) {
perror("init");
return 0;
}
outFile.open(KnobOutputFile.Value().c_str());
INS_AddInstrumentFunction(callback_instruction, 0);
PIN_AddFiniFunction(fini, 0);
PIN_StartProgram();
return 0;
}
```

Some of these 263 functions have checks that verify 2 consecutive bytes of the flag and change return value according to it. Find pattern over the check routine and use angr to solve all of them independently.

```python
import angr
# dump the rwx region from gdb
p = angr.Project("/tmp/dump", main_opts={'backend': 'blob', 'arch': 'amd64'})

start_n = [0x7f4b4a0a8a7f, 0x7f4b4a0a8b23, 0x7f4b4a0a8bc7, 0x7f4b4a0a8c6b, 0x7f4b4a0a8d0f, 0x7f4b4a0a94a2, 0x7f4b4a0a9546, 0x7f4b4a0a95ea, 0x7f4b4a0a968e, 0x7f4b4a0a9732, 0x7f4b4a0a9ec3, 0x7f4b4a0a9f67, 0x7f4b4a0aa00b, 0x7f4b4a0aa0af, 0x7f4b4a0aa153, 0x7f4b4a0aa8ec, 0x7f4b4a0aa990, 0x7f4b4a0aaa34, 0x7f4b4a0aaad8, 0x7f4b4a0aab7c, 0x7f4b4a0ab311, 0x7f4b4a0ab3b5, 0x7f4b4a0ab459, 0x7f4b4a0ab4fd, 0x7f4b4a0ab5a1, 0x7f4b4a0abd3a, 0x7f4b4a0abdde, 0x7f4b4a0abe82, 0x7f4b4a0abf26, 0x7f4b4a0abfca, 0x7f4b4a0ac75f, 0x7f4b4a0ac803, 0x7f4b4a0ac8a7, 0x7f4b4a0ac94b, 0x7f4b4a0ac9ef, 0x7f4b4a0ad186, 0x7f4b4a0ad22a, 0x7f4b4a0ad2ce, 0x7f4b4a0ad372, 0x7f4b4a0ad416, 0x7f4b4a0adba5, 0x7f4b4a0adc49, 0x7f4b4a0adced, 0x7f4b4a0add91, 0x7f4b4a0ade35, 0x7f4b4a0ae5ca, 0x7f4b4a0ae66e, 0x7f4b4a0ae712, 0x7f4b4a0ae7b6, 0x7f4b4a0ae85a, 0x7f4b4a0aeff7, 0x7f4b4a0af09b, 0x7f4b4a0af13f, 0x7f4b4a0af1e3, 0x7f4b4a0af287, 0x7f4b4a0afa22, 0x7f4b4a0afac6, 0x7f4b4a0afb6a, 0x7f4b4a0afc0e, 0x7f4b4a0afcb2, 0x7f4b4a0b0449, 0x7f4b4a0b04ed, 0x7f4b4a0b0591, 0x7f4b4a0b0635, 0x7f4b4a0b06d9, 0x7f4b4a0b0e72, 0x7f4b4a0b0f16, 0x7f4b4a0b0fba, 0x7f4b4a0b105e, 0x7f4b4a0b1102, 0x7f4b4a0b1897, 0x7f4b4a0b193b, 0x7f4b4a0b19df, 0x7f4b4a0b1a83, 0x7f4b4a0b1b27, 0x7f4b4a0b22be, 0x7f4b4a0b2362, 0x7f4b4a0b2406, 0x7f4b4a0b24aa, 0x7f4b4a0b254e, 0x7f4b4a0b2ce3, 0x7f4b4a0b2d87, 0x7f4b4a0b2e2b, 0x7f4b4a0b2ecf, 0x7f4b4a0b2f73, 0x7f4b4a0b3706, 0x7f4b4a0b37aa, 0x7f4b4a0b384e, 0x7f4b4a0b38f2, 0x7f4b4a0b3996, 0x7f4b4a0b412f, 0x7f4b4a0b41d3, 0x7f4b4a0b4277, 0x7f4b4a0b431b, 0x7f4b4a0b43bf, 0x7f4b4a0b4b54, 0x7f4b4a0b4bf8, 0x7f4b4a0b4c9c, 0x7f4b4a0b4d40, 0x7f4b4a0b4de4, 0x7f4b4a0b557b, 0x7f4b4a0b561f, 0x7f4b4a0b56c3, 0x7f4b4a0b5767, 0x7f4b4a0b580b, 0x7f4b4a0b5fa4, 0x7f4b4a0b6048, 0x7f4b4a0b60ec, 0x7f4b4a0b6190, 0x7f4b4a0b6234, 0x7f4b4a0b69cb, 0x7f4b4a0b6a6f, 0x7f4b4a0b6b13, 0x7f4b4a0b6bb7, 0x7f4b4a0b6c5b, 0x7f4b4a0b73f0, 0x7f4b4a0b7494, 0x7f4b4a0b7538, 0x7f4b4a0b75dc, 0x7f4b4a0b7680, 0x7f4b4a0b7e15, 0x7f4b4a0b7eb9, 0x7f4b4a0b7f5d, 0x7f4b4a0b8001, 0x7f4b4a0b80a5, 0x7f4b4a0b883c, 0x7f4b4a0b88e0, 0x7f4b4a0b8984, 0x7f4b4a0b8a28, 0x7f4b4a0b8acc, 0x7f4b4a0b925f, 0x7f4b4a0b9303, 0x7f4b4a0b93a7, 0x7f4b4a0b944b, 0x7f4b4a0b94ef, 0x7f4b4a0b9c88, 0x7f4b4a0b9d2c, 0x7f4b4a0b9dd0, 0x7f4b4a0b9e74, 0x7f4b4a0b9f18, 0x7f4b4a0ba6ab, 0x7f4b4a0ba74f, 0x7f4b4a0ba7f3, 0x7f4b4a0ba897, 0x7f4b4a0ba93b, 0x7f4b4a0bb0d4, 0x7f4b4a0bb178, 0x7f4b4a0bb21c, 0x7f4b4a0bb2c0, 0x7f4b4a0bb364, 0x7f4b4a0bbafb, 0x7f4b4a0bbb9f, 0x7f4b4a0bbc43, 0x7f4b4a0bbce7, 0x7f4b4a0bbd8b, 0x7f4b4a0bc522, 0x7f4b4a0bc5c6, 0x7f4b4a0bc66a, 0x7f4b4a0bc70e, 0x7f4b4a0bc7b2, 0x7f4b4a0bcf47, 0x7f4b4a0bcfeb, 0x7f4b4a0bd08f, 0x7f4b4a0bd133, 0x7f4b4a0bd1d7, 0x7f4b4a0bd96a, 0x7f4b4a0bda0e]
base = 0x7f4b4a09d000
end_n = [0x7f4b4a0a8ae7, 0x7f4b4a0a8b8b, 0x7f4b4a0a8c2f, 0x7f4b4a0a8cd3, 0x7f4b4a0a8d77, 0x7f4b4a0a950a, 0x7f4b4a0a95ae, 0x7f4b4a0a9652, 0x7f4b4a0a96f6, 0x7f4b4a0a979a, 0x7f4b4a0a9f2b, 0x7f4b4a0a9fcf, 0x7f4b4a0aa073, 0x7f4b4a0aa117, 0x7f4b4a0aa1bb, 0x7f4b4a0aa954, 0x7f4b4a0aa9f8, 0x7f4b4a0aaa9c, 0x7f4b4a0aab40, 0x7f4b4a0aabe4, 0x7f4b4a0ab379, 0x7f4b4a0ab41d, 0x7f4b4a0ab4c1, 0x7f4b4a0ab565, 0x7f4b4a0ab609, 0x7f4b4a0abda2, 0x7f4b4a0abe46, 0x7f4b4a0abeea, 0x7f4b4a0abf8e, 0x7f4b4a0ac032, 0x7f4b4a0ac7c7, 0x7f4b4a0ac86b, 0x7f4b4a0ac90f, 0x7f4b4a0ac9b3, 0x7f4b4a0aca57, 0x7f4b4a0ad1ee, 0x7f4b4a0ad292, 0x7f4b4a0ad336, 0x7f4b4a0ad3da, 0x7f4b4a0ad47e, 0x7f4b4a0adc0d, 0x7f4b4a0adcb1, 0x7f4b4a0add55, 0x7f4b4a0addf9, 0x7f4b4a0ade9d, 0x7f4b4a0ae632, 0x7f4b4a0ae6d6, 0x7f4b4a0ae77a, 0x7f4b4a0ae81e, 0x7f4b4a0ae8c2, 0x7f4b4a0af05f, 0x7f4b4a0af103, 0x7f4b4a0af1a7, 0x7f4b4a0af24b, 0x7f4b4a0af2ef, 0x7f4b4a0afa8a, 0x7f4b4a0afb2e, 0x7f4b4a0afbd2, 0x7f4b4a0afc76, 0x7f4b4a0afd1a, 0x7f4b4a0b04b1, 0x7f4b4a0b0555, 0x7f4b4a0b05f9, 0x7f4b4a0b069d, 0x7f4b4a0b0741, 0x7f4b4a0b0eda, 0x7f4b4a0b0f7e, 0x7f4b4a0b1022, 0x7f4b4a0b10c6, 0x7f4b4a0b116a, 0x7f4b4a0b18ff, 0x7f4b4a0b19a3, 0x7f4b4a0b1a47, 0x7f4b4a0b1aeb, 0x7f4b4a0b1b8f, 0x7f4b4a0b2326, 0x7f4b4a0b23ca, 0x7f4b4a0b246e, 0x7f4b4a0b2512, 0x7f4b4a0b25b6, 0x7f4b4a0b2d4b, 0x7f4b4a0b2def, 0x7f4b4a0b2e93, 0x7f4b4a0b2f37, 0x7f4b4a0b2fdb, 0x7f4b4a0b376e, 0x7f4b4a0b3812, 0x7f4b4a0b38b6, 0x7f4b4a0b395a, 0x7f4b4a0b39fe, 0x7f4b4a0b4197, 0x7f4b4a0b423b, 0x7f4b4a0b42df, 0x7f4b4a0b4383, 0x7f4b4a0b4427, 0x7f4b4a0b4bbc, 0x7f4b4a0b4c60, 0x7f4b4a0b4d04, 0x7f4b4a0b4da8, 0x7f4b4a0b4e4c, 0x7f4b4a0b55e3, 0x7f4b4a0b5687, 0x7f4b4a0b572b, 0x7f4b4a0b57cf, 0x7f4b4a0b5873, 0x7f4b4a0b600c, 0x7f4b4a0b60b0, 0x7f4b4a0b6154, 0x7f4b4a0b61f8, 0x7f4b4a0b629c, 0x7f4b4a0b6a33, 0x7f4b4a0b6ad7, 0x7f4b4a0b6b7b, 0x7f4b4a0b6c1f, 0x7f4b4a0b6cc3, 0x7f4b4a0b7458, 0x7f4b4a0b74fc, 0x7f4b4a0b75a0, 0x7f4b4a0b7644, 0x7f4b4a0b76e8, 0x7f4b4a0b7e7d, 0x7f4b4a0b7f21, 0x7f4b4a0b7fc5, 0x7f4b4a0b8069, 0x7f4b4a0b810d, 0x7f4b4a0b88a4, 0x7f4b4a0b8948, 0x7f4b4a0b89ec, 0x7f4b4a0b8a90, 0x7f4b4a0b8b34, 0x7f4b4a0b92c7, 0x7f4b4a0b936b, 0x7f4b4a0b940f, 0x7f4b4a0b94b3, 0x7f4b4a0b9557, 0x7f4b4a0b9cf0, 0x7f4b4a0b9d94, 0x7f4b4a0b9e38, 0x7f4b4a0b9edc, 0x7f4b4a0b9f80, 0x7f4b4a0ba713, 0x7f4b4a0ba7b7, 0x7f4b4a0ba85b, 0x7f4b4a0ba8ff, 0x7f4b4a0ba9a3, 0x7f4b4a0bb13c, 0x7f4b4a0bb1e0, 0x7f4b4a0bb284, 0x7f4b4a0bb328, 0x7f4b4a0bb3cc, 0x7f4b4a0bbb63, 0x7f4b4a0bbc07, 0x7f4b4a0bbcab, 0x7f4b4a0bbd4f, 0x7f4b4a0bbdf3, 0x7f4b4a0bc58a, 0x7f4b4a0bc62e, 0x7f4b4a0bc6d2, 0x7f4b4a0bc776, 0x7f4b4a0bc81a, 0x7f4b4a0bcfaf, 0x7f4b4a0bd053, 0x7f4b4a0bd0f7, 0x7f4b4a0bd19b, 0x7f4b4a0bd23f, 0x7f4b4a0bd9d2, 0x7f4b4a0bda76]

start = [i-base-0x17 for i in start_n]
end = [i-base+0x13 for i in end_n]
avoid = [i-base+0xc for i in end_n]

def return_two(ex, idx):
return chr(ex.found[0].solver.eval(ex.found[0].memory.load(flag_addr+idx, 1)))+chr(ex.found[0].solver.eval(ex.found[0].memory.load(flag_addr+idx+1, 1)))
s = ""
# each check involves 2 contiguous bytes -> length 334/2
for i in range(167):
state = p.factory.blank_state(addr=start[i])
flag_addr = 0x1000
for ii in range(i*2, i*2+2):
state.mem[flag_addr + ii].byte = state.solver.BVS('c', 8)

state.memory.store(0x2000, 0x1000+i*2, endness='Iend_LE')
state.memory.store(state.regs.rbp - 0x58, 0x2000, endness='Iend_LE')

ex = p.factory.simulation_manager(state)
ex.explore(find=end[i], avoid=avoid[i])
# raw_input()
s += return_two(ex, i*2)
print(i)
print(s)
```

Original writeup (https://gist.github.com/sudhackar/ad9c15851f274b3248ef1645abee9ae8#file-step_4_angr_solve-py).