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```pythonsize_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 = 0code_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.
```pythonimport angr# dump the rwx region from gdbp = 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 = 0x7f4b4a09d000end_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/2for 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)```
