├── README.md ├── Rewrite ├── deob.c └── deob │ ├── emulation.h │ ├── flags.h │ ├── insn_utility.h │ ├── list.h │ ├── op_utility.h │ ├── optimizations.h │ ├── optimizations_old.h │ ├── structures.h │ └── tests.h ├── deobfuscator_test.c └── t4y.7z /README.md: -------------------------------------------------------------------------------- 1 | # DeobfuscatorTest 2 | This tool is a personal study on obfuscation & de-obfuscation techniques. It is badly implemented and I will work on it only if University leaves me enough time. 3 | Don't ask for help on cracking protections because it is unethical and I'm not going to help. Reverse, learn & study, but don't ruin other people work. 4 | # Rewrite 5 | In the folder rewrite there is the code I'm updating and rewriting to make it more clear. 6 | -------------------------------------------------------------------------------- /Rewrite/deob.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | //define the general list 7 | static List *list = NULL; 8 | 9 | #define TEST_BUILD false 10 | 11 | int test_main() { 12 | //place here the test code and enable TEST_BUILD flag 13 | ExitProcess(EXIT_SUCCESS); 14 | } 15 | 16 | int main(int argc, char **argv) { 17 | srand(time(NULL)); 18 | if(TEST_BUILD) test_main(); 19 | // Importing XEDParseAssemble from the dynamic library 20 | HANDLE XEDLib = LoadLibrary("XEDParse.dll"); 21 | if(XEDLib == NULL) { 22 | printf("[-] Error: LoadLibrary - 0x%x\n", GetLastError()); 23 | return EXIT_FAILURE; 24 | } 25 | assemble = (XEDParseAssemble)GetProcAddress(XEDLib, "XEDParseAssemble"); 26 | if(assemble == NULL) { 27 | printf("[-] Error: GetProcAddress - 0x%x\n", GetLastError()); 28 | return EXIT_FAILURE; 29 | } 30 | // Optimizing for stack operations 31 | csh handle; 32 | cs_insn *insn; 33 | cs_err err; 34 | size_t count; 35 | err = cs_open(CS_ARCH_X86, MODE, &handle); 36 | if(err != CS_ERR_OK) { 37 | printf("[-] Error: cs_open.\n"); 38 | return -1; 39 | } 40 | //I want all possible details 41 | cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); 42 | count = cs_disasm(handle, CODE, sizeof(CODE)-1, 0x1000, 0, &insn); 43 | if(count > 0) { 44 | //create list 45 | list = ListCreate(); 46 | //adding original instructions to list 47 | Instruction *current = NULL; 48 | ListEntry *entry = NULL; 49 | for(size_t i = 0; i < count; i++) { 50 | current = calloc(1, sizeof(Instruction)); 51 | current->insn = (cs_insn *)calloc(1, sizeof(cs_insn)); 52 | memcpy(current->insn, &insn[i], sizeof(cs_insn)); 53 | entry = ListEntryCreate(current); 54 | ListPush(list, entry); 55 | } 56 | printf("[!] Original code\n\n"); 57 | print_disassembly(handle, list, INFO); 58 | //init a fake initial registers context that will be used across the execution 59 | Registers *start_regs; 60 | init_reg_context(&start_regs, STACK_ADDRESS, MODE); 61 | //emulate the obfuscated code and save the end registers context result 62 | Registers *end_regs = calloc(1, sizeof(Registers)); 63 | List *mem_writes = ListCreate(); 64 | emulate_context(handle, list, start_regs, end_regs, mem_writes, MODE); 65 | if(!ListIsEmpty(mem_writes)) printf("The following memory locations are WRITE\n"); 66 | print_memory_value(mem_writes); 67 | //start main optimization loop 68 | bool optimized; 69 | //first pass 70 | if(FIRST_PASS) { 71 | do { 72 | optimized = false; 73 | while(expand_stack_ins(handle, list, MODE)) { optimized = true; } 74 | while(collapse_add_sub(handle, list, MODE)) { optimized = true; } 75 | while(emulate_stack_reg(handle, list, start_regs, MODE)) { optimized = true; } 76 | } while(optimized); 77 | } 78 | //show code after main optimization loop 79 | if(VERBOSE) { 80 | printf("\n\n------------ Temporary code 1 ------------\n\n"); 81 | print_disassembly(handle, list, INFO); 82 | //emulate new context 83 | Registers *end_regs_new = calloc(1, sizeof(Registers)); 84 | List *mem_writes_new = ListCreate(); 85 | emulate_context(handle, list, start_regs, end_regs_new, mem_writes_new, MODE); 86 | if(check_context_integrity(end_regs, mem_writes, end_regs_new, mem_writes_new)) { 87 | printf("\n[OK] Integrity kept! :D\n"); 88 | } else { 89 | printf("\n[NO] Integrity destroyed! D:\n"); 90 | } 91 | } 92 | //free memory 93 | ListDestroy(mem_writes); 94 | free(end_regs); 95 | free(start_regs); 96 | cs_free(insn, count); 97 | } else { 98 | printf("[-] Error: cs_disasm.\n"); 99 | } 100 | cs_close(&handle); 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /Rewrite/deob/emulation.h: -------------------------------------------------------------------------------- 1 | uint64_t random_reg_value() { 2 | uint64_t num = rand(); 3 | num = (num << 32 | rand()); 4 | num = (num % (999999999 - 100000000)) + 100000000; 5 | return num; 6 | } 7 | 8 | static bool hook_mem_invalid(uc_engine *uc, uc_mem_type type, uint64_t addr, int size, int64_t value, void *user_data) { 9 | //printf("old addr: 0x%llx\n", addr); 10 | switch(MODE) { 11 | case CS_MODE_32: 12 | addr &= 0xFFFFF000; 13 | break; 14 | case CS_MODE_64: 15 | addr &= 0xFFFFFFFFFFFFF000; 16 | break; 17 | } 18 | //printf("new addr: 0x%llx\n", addr); 19 | uc_err err; 20 | switch(type) { 21 | default: 22 | //printf("UC_HOOK_MEM_INVALID type: %d at 0x%" PRIx64 "\n", type, addr); 23 | // map this memory in with 2MB in size 24 | err = uc_mem_map(uc, addr, 2 * 1024*1024, UC_PROT_ALL); 25 | // return true to indicate we want to continue 26 | return true; 27 | case UC_MEM_READ_UNMAPPED: 28 | //printf("UC_MEM_READ_UNMAPPED at 0x%"PRIx64 ", data size = %u\n", addr, size); 29 | // map this memory in with 2MB in size 30 | err = uc_mem_map(uc, addr, 2 * 1024*1024, UC_PROT_ALL); 31 | // return true to indicate we want to continue 32 | return true; 33 | case UC_MEM_WRITE_UNMAPPED: 34 | //printf("UC_MEM_WRITE_UNMAPPED at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value); 35 | // map this memory in with 2MB in size 36 | err = uc_mem_map(uc, addr, 2 * 1024*1024, UC_PROT_ALL); 37 | // return true to indicate we want to continue 38 | return true; 39 | case UC_MEM_FETCH_PROT: 40 | //printf("UC_MEM_FETCH_PROT at 0x%"PRIx64 "\n", addr); 41 | // map this memory in with 2MB in size 42 | err = uc_mem_map(uc, addr, 2 * 1024*1024, UC_PROT_ALL); 43 | // return true to indicate we want to continue 44 | return true; 45 | case UC_MEM_WRITE_PROT: 46 | //printf("UC_MEM_WRITE_PROT at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value); 47 | // map this memory in with 2MB in size 48 | err = uc_mem_map(uc, addr, 2 * 1024*1024, UC_PROT_ALL); 49 | // return true to indicate we want to continue 50 | return true; 51 | case UC_MEM_READ_PROT: 52 | //printf("UC_MEM_READ_PROT at 0x%"PRIx64 ", data size = %u\n", addr, size); 53 | // map this memory in with 2MB in size 54 | err = uc_mem_map(uc, addr, 2 * 1024*1024, UC_PROT_ALL); 55 | // return true to indicate we want to continue 56 | return true; 57 | } 58 | } 59 | 60 | static bool hook_mem_access(uc_engine *uc, uc_mem_type type, uint64_t addr, int size, int64_t value, void *user_data) { 61 | List *mem_list = (List *)user_data; 62 | switch(type) { 63 | default: break; 64 | case UC_MEM_READ: 65 | //printf(">>> Memory is being READ at 0x%"PRIx64 ", data size = %u\n", addr, size); 66 | break; 67 | case UC_MEM_WRITE: 68 | if(!(addr >= STACK_ADDRESS && addr <= (STACK_ADDRESS + EMU_SIZE))) { 69 | //if(VERBOSE) printf(">>> Memory is being WRITE at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value); 70 | if(mem_list) { 71 | MemoryValue *mem_val = calloc(1, sizeof(MemoryValue)); 72 | mem_val->address = addr; 73 | mem_val->size = size; 74 | mem_val->value = value; 75 | ListEntry *new_entry = ListEntryCreate(mem_val); 76 | ListPush(mem_list, new_entry); 77 | } 78 | } 79 | break; 80 | } 81 | } 82 | 83 | static void hook_code(uc_engine *uc, uint64_t address, int32_t size, void *user_data) { 84 | //this function could be used to trace & modify operation while emulating code 85 | /*printf("EIP/RIP: 0x%llx, SIZE: 0x%llx\n", address, size); 86 | uint32_t rsp; 87 | uc_reg_read(uc, UC_X86_REG_ESP, &rsp); 88 | printf("[!] rsp: 0x%x\n", rsp); 89 | uint8_t bytes[0xFF]; 90 | uc_mem_read(uc, address, bytes, size); 91 | printf("[!] bytes: "); 92 | for(size_t i = 0; i < size; i++) { 93 | printf("%02x ", bytes[i]); 94 | } 95 | printf("\n");*/ 96 | } 97 | 98 | /* 99 | Name: print_reg_context 100 | Description: outputs the register context passed as argument 101 | */ 102 | void print_reg_context(csh handle, Registers *regs, uint8_t mode) { 103 | printf("\n[!] Register Context\n"); 104 | uint8_t reg_name[0x10] = { 105 | X86_REG_RAX, X86_REG_RBX, X86_REG_RCX, X86_REG_RDX, X86_REG_RBP, X86_REG_RSP, X86_REG_RSI, X86_REG_RDI, 106 | X86_REG_R8, X86_REG_R9, X86_REG_R10, X86_REG_R11, X86_REG_R12, X86_REG_R13, X86_REG_R14, X86_REG_R15 107 | }; 108 | uint32_t count = (mode == CS_MODE_32) ? 8 : 16; 109 | for(size_t i = 0; i < count; i++) { 110 | printf("%s = 0x%llx\n", cs_reg_name(handle, reg_name[i]), ((uint64_t **)regs)[i]); 111 | } 112 | } 113 | 114 | /* 115 | Name: init_regs_context 116 | Description: this function initializes a registry context given a pointer to the structure 117 | and a mode (CS_MODE_32 or CS_MODE_64). The stack address is used to initialize the ESP/RSP 118 | value; the other registers are initialized at random values. 119 | */ 120 | void init_reg_context(Registers **regs, uint64_t stack_address, uint8_t mode) { 121 | //remember to free the allocation as soon as you don't need it anymore 122 | *regs = (Registers *)calloc(1, sizeof(Registers)); 123 | //every register is initialized with a random value 124 | (*regs)->rax = random_reg_value(); 125 | (*regs)->rbx = random_reg_value(); 126 | (*regs)->rcx = random_reg_value(); 127 | (*regs)->rdx = random_reg_value(); 128 | (*regs)->rbp = random_reg_value(); 129 | (*regs)->rsp = stack_address + (stack_address / 2); 130 | (*regs)->rsi = random_reg_value(); 131 | (*regs)->rdi = random_reg_value(); 132 | //if the mode is CS_MODE_64 also r8-r15 are initialized 133 | if(mode == CS_MODE_64) { 134 | (*regs)->r8 = random_reg_value(); 135 | (*regs)->r9 = random_reg_value(); 136 | (*regs)->r10 = random_reg_value(); 137 | (*regs)->r11 = random_reg_value(); 138 | (*regs)->r12 = random_reg_value(); 139 | (*regs)->r13 = random_reg_value(); 140 | (*regs)->r14 = random_reg_value(); 141 | (*regs)->r15 = random_reg_value(); 142 | } 143 | } 144 | 145 | /* 146 | Name: copy_reg_context 147 | Description: this function copies the registers context from 'old_c' to 'new_c'. 148 | */ 149 | bool copy_reg_context(Registers *old_c, Registers *new_c) { 150 | if(!old_c) return true; 151 | if(!new_c) return false; 152 | //the full x64 context is copied here, also if uninitialized 153 | memcpy(new_c, old_c, sizeof(Registers)); 154 | return true; 155 | } 156 | 157 | /* 158 | Name: emulate_code 159 | Description: this function emulates assembly instructions starting from 'start' to 'end'. 160 | A register context is passed to the function to be used as starting point and updated 161 | with new values at the emulation end. Also a MemoryLocation list can be passed, and it will 162 | be updated with address-value of each WRITE. 163 | */ 164 | void emulate_code(csh handle, ListEntry *start, ListEntry *end, Registers *regs, List *mem, uint8_t mode) { 165 | if(!regs) return; 166 | //generate the byte array to be emulated 167 | uint64_t assembly_size = 0; 168 | if(!start) return; 169 | ListEntry *current = start; 170 | Instruction *instruction; 171 | while(current && current != end) { 172 | instruction = (Instruction *)current->content; 173 | assembly_size += instruction->insn->size; 174 | current = current->next; 175 | } 176 | uint8_t *assembly = calloc(assembly_size, sizeof(uint8_t)); 177 | current = start; 178 | uint64_t index = 0; 179 | while(current && current != end) { 180 | instruction = (Instruction *)current->content; 181 | memcpy((assembly + index), instruction->insn->bytes, instruction->insn->size); 182 | index += instruction->insn->size; 183 | current = current->next; 184 | } 185 | //setup emulation environment 186 | uc_engine *uc; 187 | uc_err err; 188 | err = uc_open(UC_ARCH_X86, mode, &uc); 189 | if(err != UC_ERR_OK) { 190 | printf("[-] Error: uc_open, %s\n", uc_strerror(err)); 191 | return; 192 | } 193 | //mapping .text memory, but one should actually allocate every useful piece of memory 194 | err = uc_mem_map(uc, TEXT_ADDRESS, EMU_SIZE, UC_PROT_ALL); 195 | if(err != UC_ERR_OK) { 196 | printf("[-] Error: uc_mem_map, %s\n", uc_strerror(err)); 197 | return; 198 | } 199 | //mapping .stack memory (at a standard address, is not really important to be specific) 200 | err = uc_mem_map(uc, STACK_ADDRESS, EMU_SIZE, UC_PROT_ALL); 201 | if(err != UC_ERR_OK) { 202 | printf("[-] Error: uc_mem_map, %s\n", uc_strerror(err)); 203 | return; 204 | } 205 | /*if(VERBOSE) { 206 | printf("[I] Machine code to be emulated:\n"); 207 | for(size_t i = 0; i < assembly_size; i++) { 208 | printf("%x ", assembly[i]); 209 | } 210 | }*/ 211 | //writing machine code to .text memory 212 | err = uc_mem_write(uc, TEXT_ADDRESS, assembly, assembly_size); 213 | if(err != UC_ERR_OK) { 214 | printf("[-] Error: uc_mem_write, %s\n", uc_strerror(err)); 215 | return; 216 | } 217 | //adding hook to trace-step instructions 218 | uc_hook hook_id = 0, hook_id_2 = 0, hook_id_3 = 0; 219 | //trace every instruction 220 | uc_hook_add(uc, &hook_id, UC_HOOK_CODE, hook_code, NULL, TEXT_ADDRESS, TEXT_ADDRESS + assembly_size); 221 | //intercept invalid memory events 222 | uc_hook_add(uc, &hook_id_2, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL, (uint64_t)1, (uint64_t)0); 223 | //intercept memory access 224 | uc_hook_add(uc, &hook_id_3, UC_HOOK_MEM_WRITE|UC_HOOK_MEM_READ, hook_mem_access, mem, (uint64_t)1, (uint64_t)0); 225 | //write registers to emulation context 226 | switch(mode) { 227 | case CS_MODE_32: 228 | uc_reg_write(uc, UC_X86_REG_EAX, &(regs->rax)); 229 | uc_reg_write(uc, UC_X86_REG_EBX, &(regs->rbx)); 230 | uc_reg_write(uc, UC_X86_REG_ECX, &(regs->rcx)); 231 | uc_reg_write(uc, UC_X86_REG_EDX, &(regs->rdx)); 232 | uc_reg_write(uc, UC_X86_REG_ESP, &(regs->rsp)); 233 | uc_reg_write(uc, UC_X86_REG_EBP, &(regs->rbp)); 234 | uc_reg_write(uc, UC_X86_REG_ESI, &(regs->rsi)); 235 | uc_reg_write(uc, UC_X86_REG_EDI, &(regs->rdi)); 236 | break; 237 | case CS_MODE_64: 238 | uc_reg_write(uc, UC_X86_REG_RAX, &(regs->rax)); 239 | uc_reg_write(uc, UC_X86_REG_RBX, &(regs->rbx)); 240 | uc_reg_write(uc, UC_X86_REG_RCX, &(regs->rcx)); 241 | uc_reg_write(uc, UC_X86_REG_RDX, &(regs->rdx)); 242 | uc_reg_write(uc, UC_X86_REG_RSP, &(regs->rsp)); 243 | uc_reg_write(uc, UC_X86_REG_RBP, &(regs->rbp)); 244 | uc_reg_write(uc, UC_X86_REG_RSI, &(regs->rsi)); 245 | uc_reg_write(uc, UC_X86_REG_RDI, &(regs->rdi)); 246 | uc_reg_write(uc, UC_X86_REG_R8, &(regs->r8)); 247 | uc_reg_write(uc, UC_X86_REG_R9, &(regs->r9)); 248 | uc_reg_write(uc, UC_X86_REG_R10, &(regs->r10)); 249 | uc_reg_write(uc, UC_X86_REG_R11, &(regs->r11)); 250 | uc_reg_write(uc, UC_X86_REG_R12, &(regs->r12)); 251 | uc_reg_write(uc, UC_X86_REG_R13, &(regs->r13)); 252 | uc_reg_write(uc, UC_X86_REG_R14, &(regs->r14)); 253 | uc_reg_write(uc, UC_X86_REG_R15, &(regs->r15)); 254 | break; 255 | } 256 | //emulate code 257 | uint64_t esp = 0; 258 | uc_reg_read(uc, UC_X86_REG_ESP, &esp); 259 | err = uc_emu_start(uc, TEXT_ADDRESS, TEXT_ADDRESS + assembly_size, 0, 0); 260 | if(err != UC_ERR_OK) { 261 | printf("[-] Error: uc_emu_start, %s\n", uc_strerror(err)); 262 | return; 263 | } 264 | //delete hook 265 | uc_hook_del(uc, hook_id); 266 | uc_hook_del(uc, hook_id_2); 267 | uc_hook_del(uc, hook_id_3); 268 | //read registers from emulation context 269 | switch(mode) { 270 | case CS_MODE_32: 271 | uc_reg_read(uc, UC_X86_REG_EAX, &(regs->rax)); 272 | uc_reg_read(uc, UC_X86_REG_EBX, &(regs->rbx)); 273 | uc_reg_read(uc, UC_X86_REG_ECX, &(regs->rcx)); 274 | uc_reg_read(uc, UC_X86_REG_EDX, &(regs->rdx)); 275 | uc_reg_read(uc, UC_X86_REG_ESP, &(regs->rsp)); 276 | uc_reg_read(uc, UC_X86_REG_EBP, &(regs->rbp)); 277 | uc_reg_read(uc, UC_X86_REG_ESI, &(regs->rsi)); 278 | uc_reg_read(uc, UC_X86_REG_EDI, &(regs->rdi)); 279 | break; 280 | case CS_MODE_64: 281 | 282 | uc_reg_read(uc, UC_X86_REG_RAX, &(regs->rax)); 283 | uc_reg_read(uc, UC_X86_REG_RBX, &(regs->rbx)); 284 | uc_reg_read(uc, UC_X86_REG_RCX, &(regs->rcx)); 285 | uc_reg_read(uc, UC_X86_REG_RDX, &(regs->rdx)); 286 | uc_reg_read(uc, UC_X86_REG_RSP, &(regs->rsp)); 287 | uc_reg_read(uc, UC_X86_REG_RBP, &(regs->rbp)); 288 | uc_reg_read(uc, UC_X86_REG_RSI, &(regs->rsi)); 289 | uc_reg_read(uc, UC_X86_REG_RDI, &(regs->rdi)); 290 | uc_reg_read(uc, UC_X86_REG_R8, &(regs->r8)); 291 | uc_reg_read(uc, UC_X86_REG_R9, &(regs->r9)); 292 | uc_reg_read(uc, UC_X86_REG_R10, &(regs->r10)); 293 | uc_reg_read(uc, UC_X86_REG_R11, &(regs->r11)); 294 | uc_reg_read(uc, UC_X86_REG_R12, &(regs->r12)); 295 | uc_reg_read(uc, UC_X86_REG_R13, &(regs->r13)); 296 | uc_reg_read(uc, UC_X86_REG_R14, &(regs->r14)); 297 | uc_reg_read(uc, UC_X86_REG_R15, &(regs->r15)); 298 | break; 299 | } 300 | //freeing assembly 301 | free(assembly); 302 | } 303 | 304 | /* 305 | Name: emulate_context 306 | Description: this function emulates the registry and memory context after the execution of the code 307 | contained in the List passed as argument. If mod_reg & mem are NULL the context is only displayed 308 | if the VERBOSE flag is set, and not saved. 309 | */ 310 | void emulate_context(csh handle, List *list, Registers *regs, Registers *mod_regs, List *mem, uint8_t mode) { 311 | //find which registers are changing 312 | Registers *old_regs = calloc(1, sizeof(Registers)); 313 | //copying old registers to be able to check after emulation 314 | copy_reg_context(regs, old_regs); 315 | //emulate code from first to last instruction 316 | emulate_code(handle, list->first, list->last->next, regs, mem, mode); 317 | //check which register is changed and save the instructions modifying it 318 | uint8_t reg_name[16] = { 319 | X86_REG_RAX, X86_REG_RBX, X86_REG_RCX, X86_REG_RDX, X86_REG_RBP, X86_REG_RSP, X86_REG_RSI, X86_REG_RDI, 320 | X86_REG_R8, X86_REG_R9, X86_REG_R10, X86_REG_R11, X86_REG_R12, X86_REG_R13, X86_REG_R14, X86_REG_R15 321 | }; 322 | if(VERBOSE) printf("\n[!] The following registers are changed\n"); 323 | uint64_t old_reg, new_reg; 324 | for(size_t i = 0; i < 16; i++) { 325 | old_reg = (uint64_t)((uint64_t **)old_regs)[i]; 326 | new_reg = (uint64_t)((uint64_t **)regs)[i]; 327 | if(mod_regs) ((uint64_t *)mod_regs)[i] = new_reg; 328 | if(old_reg != new_reg) { 329 | if(VERBOSE) printf("%s [OLD = 0x%llx][NEW = 0x%llx]\n", cs_reg_name(handle, reg_name[i]), old_reg, new_reg); 330 | } 331 | } 332 | //reset original regs 333 | copy_reg_context(old_regs, regs); 334 | //freeing space 335 | free(old_regs); 336 | } 337 | 338 | /* 339 | Name: check_context_integrity 340 | Description: this function does a simple context integrity check, but it does not check the semantic 341 | of the executed code. Given a knowm and unknown register & memory context, the two are 342 | compared and if something different is found the result is FALSE. 343 | */ 344 | bool check_context_integrity(Registers *old_regs, List *old_mem, Registers *new_regs, List *new_mem) { 345 | bool integrity_kept = true; 346 | //check first the register context 347 | if(old_regs && new_regs) 348 | integrity_kept = (memcmp(old_regs, new_regs, sizeof(Registers)) == 0) ? true : false; 349 | if(old_mem && new_mem && old_mem->entry_count > 0) { 350 | ListEntry *current = old_mem->first; 351 | while(integrity_kept && old_mem->entry_count > 0) { 352 | integrity_kept = ListCmpEntries(ListPop(old_mem), ListPop(new_mem), sizeof(MemoryValue)); 353 | } 354 | } 355 | return integrity_kept; 356 | } 357 | -------------------------------------------------------------------------------- /Rewrite/deob/flags.h: -------------------------------------------------------------------------------- 1 | //Display flags 2 | #define INFO true 3 | #define SHOW_ADDR false 4 | #define VERBOSE true 5 | #define VERBOSE_ERROR true 6 | #define ENABLE_TEST_FUNCTIONS true 7 | 8 | //Emulation testing values 9 | #define TEXT_ADDRESS 0x401000 10 | #define STACK_ADDRESS 0x1000 11 | #define EMU_SIZE 2 * 1024 * 1024 12 | 13 | //Optimizations flags 14 | #define FIRST_PASS true 15 | #define SECOND_PASS true 16 | 17 | //junk elimination 18 | #define REMOVE_FLAG_INS true 19 | #define REMOVE_UNUSED false 20 | 21 | //Stack expansion 22 | #define STACK_DISPLACEMENT 0x400 23 | 24 | /* Importing XEDParseAssemble */ 25 | 26 | typedef XEDPARSE_STATUS (WINAPI *XEDParseAssemble)(XEDPARSE *xed_parse); 27 | XEDParseAssemble assemble; 28 | -------------------------------------------------------------------------------- /Rewrite/deob/insn_utility.h: -------------------------------------------------------------------------------- 1 | /* Useful information extraction functions */ 2 | 3 | /* 4 | Name: is_memory_insn 5 | Description: this function checks if the instruction uses a 6 | memory location. Returns FALSE if 'current' is NULL or if 7 | the 'current' instruction is not using memory. 8 | */ 9 | bool is_memory_insn(Instruction *current) { 10 | if(!current) return false; 11 | cs_x86 *x86 = &(current->insn->detail->x86); 12 | size_t op_count = x86->op_count; 13 | cs_x86_op *op; 14 | for(size_t i = 0; i < op_count; i++) { 15 | op = &(x86->operands[i]); 16 | if(op->type == X86_OP_MEM) { 17 | return true; 18 | } 19 | } 20 | return false; 21 | } 22 | 23 | /* 24 | Name: get_op_count 25 | Description: this function retrieves the op_coun for a given instruction. 26 | */ 27 | size_t get_op_count(Instruction *current) { 28 | cs_x86 *x86 = &(current->insn->detail->x86); 29 | return x86->op_count; 30 | } 31 | 32 | /* 33 | Name: get_op_size 34 | Description: this function extracts the operand size of an operand, given the operand position. 35 | */ 36 | bool get_op_size(Instruction *current, RegPosition position, uint8_t *size) { 37 | if(!current) return false; 38 | size_t op_count = get_op_count(current); 39 | if(position < op_count) { 40 | *size = current->insn->detail->x86.operands[position].size; 41 | return true; 42 | } 43 | return false; 44 | } 45 | 46 | /* 47 | Name: get_id 48 | Description: this function gets the ID from the current instruction 49 | */ 50 | uint32_t get_id(Instruction *current) { 51 | return current->insn->id; 52 | } 53 | 54 | /* 55 | Name: set_id 56 | Description: this function sets a new ID for the given instruction. 57 | */ 58 | void set_id(Instruction *current, uint32_t id) { 59 | current->insn->id = id; 60 | } 61 | 62 | /* 63 | Name: get_reg_at 64 | Description: this function extracts the register value given an index 65 | indicating the operand position. If the given position is invalid 66 | (greater than the number of operands or the operand at that posiztion 67 | is not a register) the returned value id X86_REG_INVALID. 68 | */ 69 | uint8_t get_reg_at(Instruction *current, RegPosition position) { 70 | if(!current) return X86_REG_INVALID; 71 | cs_x86 *x86 = &(current->insn->detail->x86); 72 | size_t op_count = x86->op_count; 73 | if(position < op_count) { 74 | if(x86->operands[position].type == X86_OP_REG) { 75 | return x86->operands[position].reg; 76 | } 77 | } 78 | return X86_REG_INVALID; 79 | } 80 | 81 | /* 82 | Name: get_base 83 | Description: this function extracts the base register used by the 84 | instruction. If not found, it return X86_REG_INVALID. 85 | */ 86 | uint8_t get_base(Instruction *current) { 87 | if(!current) return X86_REG_INVALID; 88 | if(!is_memory_insn(current)) return X86_REG_INVALID; 89 | cs_x86 *x86 = &(current->insn->detail->x86); 90 | size_t op_count = x86->op_count; 91 | cs_x86_op *op; 92 | for(size_t i = 0; i < op_count; i++) { 93 | op = &(x86->operands[i]); 94 | if(op->type == X86_OP_MEM) { 95 | return op->mem.base; 96 | } 97 | } 98 | return X86_REG_INVALID; 99 | } 100 | 101 | /* 102 | Name: get_index 103 | Description: this function extracts the index register used by the 104 | instruction. If not found, it return X86_REG_INVALID. 105 | */ 106 | uint8_t get_index(Instruction *current) { 107 | if(!is_memory_insn(current)) return X86_REG_INVALID; 108 | cs_x86 *x86 = &(current->insn->detail->x86); 109 | size_t op_count = x86->op_count; 110 | cs_x86_op *op; 111 | for(size_t i = 0; i < op_count; i++) { 112 | op = &(x86->operands[i]); 113 | if(op->type == X86_OP_MEM) { 114 | return op->mem.index; 115 | } 116 | } 117 | return X86_REG_INVALID; 118 | } 119 | 120 | /* 121 | Name: get_disp 122 | Description: this function extracts the displacement used by the memory 123 | instruction. 124 | */ 125 | bool get_disp(Instruction *current, uint32_t *disp) { 126 | if(!is_memory_insn(current)) return X86_REG_INVALID; 127 | cs_x86 *x86 = &(current->insn->detail->x86); 128 | size_t op_count = x86->op_count; 129 | cs_x86_op *op; 130 | for(size_t i = 0; i < op_count; i++) { 131 | op = &(x86->operands[i]); 132 | if(op->type == X86_OP_MEM) { 133 | *disp = op->mem.disp; 134 | return true; 135 | } 136 | } 137 | return false; 138 | } 139 | 140 | /* 141 | Name: get_scale 142 | Description: this function extracts the scale used by the memory instruction. 143 | */ 144 | bool get_scale(Instruction *current, uint32_t *scale) { 145 | if(!is_memory_insn(current)) return X86_REG_INVALID; 146 | cs_x86 *x86 = &(current->insn->detail->x86); 147 | size_t op_count = x86->op_count; 148 | cs_x86_op *op; 149 | for(size_t i = 0; i < op_count; i++) { 150 | op = &(x86->operands[i]); 151 | if(op->type == X86_OP_MEM) { 152 | *scale = op->mem.scale; 153 | return true; 154 | } 155 | } 156 | return false; 157 | } 158 | 159 | /* 160 | Name: get_imm 161 | Description: this function extracts the immediate value and if not found, 162 | the returned value is FALSE, otherwise it is TRUE and the immediate is saved 163 | on the 'imm' arguments. 164 | */ 165 | bool get_imm(Instruction *current, uint64_t *imm) { 166 | cs_x86 *x86 = &(current->insn->detail->x86); 167 | size_t op_count = x86->op_count; 168 | cs_x86_op *op; 169 | for(size_t i = 0; i < op_count; i++) { 170 | op = &(x86->operands[i]); 171 | if(op->type == X86_OP_IMM) { 172 | *imm = op->imm; 173 | return true; 174 | } 175 | } 176 | return false; 177 | } 178 | 179 | /* 180 | Name: set_disp 181 | Description: this function is used to update the displacement on a 182 | memory operation with the one passed as argument. 183 | */ 184 | bool set_disp(Instruction *current, uint32_t disp) { 185 | if(!current) return false; 186 | if(!is_memory_insn(current)) return false; 187 | cs_x86 *x86 = &(current->insn->detail->x86); 188 | size_t op_count = x86->op_count; 189 | cs_x86_op *op; 190 | for(size_t i = 0; i < op_count; i++) { 191 | op = &(x86->operands[i]); 192 | if(op->type == X86_OP_MEM) { 193 | op->mem.disp = disp; 194 | return true; 195 | } 196 | } 197 | return false; 198 | } 199 | 200 | /* 201 | Name: set_imm 202 | Description: this function is used to update the immediate of an 203 | instruction with the one passed as argument. 204 | */ 205 | bool set_imm(Instruction *current, uint64_t imm) { 206 | if(!current) return false; 207 | cs_x86 *x86 = &(current->insn->detail->x86); 208 | size_t op_count = x86->op_count; 209 | cs_x86_op *op; 210 | for(size_t i = 0; i < op_count; i++) { 211 | op = &(x86->operands[i]); 212 | if(op->type == X86_OP_IMM) { 213 | op->imm = imm; 214 | return true; 215 | } 216 | } 217 | return false; 218 | } 219 | 220 | /* 221 | Name: set_reg_at 222 | Description: this function sets the register at the location indicated 223 | by 'position'. 224 | */ 225 | bool set_reg_at(Instruction *current, RegPosition position, uint8_t reg) { 226 | if(!current) return false; 227 | size_t op_count = get_op_count(current); 228 | if(position < op_count) { 229 | if(current->insn->detail->x86.operands[position].type != X86_OP_REG) return false; 230 | current->insn->detail->x86.operands[position].reg = reg; 231 | return true; 232 | } 233 | return false; 234 | } 235 | 236 | /* 237 | Name: get_mem_size 238 | Description: this function returns the memory size indicator if found; 239 | it can be 1/2/4/8. If not found the result is FALSE. 240 | */ 241 | bool get_mem_size(Instruction *current, uint8_t *size) { 242 | if(!is_memory_insn(current)) return X86_REG_INVALID; 243 | cs_x86 *x86 = &(current->insn->detail->x86); 244 | size_t op_count = x86->op_count; 245 | cs_x86_op *op; 246 | for(size_t i = 0; i < op_count; i++) { 247 | op = &(x86->operands[i]); 248 | if(op->type == X86_OP_MEM) { 249 | *size = op->size; 250 | return true; 251 | } 252 | } 253 | return false; 254 | } 255 | 256 | /* 257 | Name: get_mem_indicator 258 | Description: this function returns a string representation of the 259 | memory indicator given in input the size value. 260 | */ 261 | char *get_mem_indicator(uint8_t size) { 262 | //remember to free the allocation when unused 263 | char *indicator = calloc(8, sizeof(char)); 264 | switch(size) { 265 | case 1: 266 | sprintf(indicator, "byte"); 267 | break; 268 | case 2: 269 | sprintf(indicator, "word"); 270 | break; 271 | case 4: 272 | sprintf(indicator, "dword"); 273 | break; 274 | case 8: 275 | sprintf(indicator, "qword"); 276 | break; 277 | default: break; 278 | } 279 | return indicator; 280 | } 281 | 282 | /* 283 | Name: is_dst_reg 284 | Description: this function checks if the destination is a register 285 | */ 286 | bool is_dst_reg(Instruction *current) { 287 | if(!current) return false; 288 | cs_x86 *x86 = current->insn->detail->x86; 289 | uint8_t type = x86->operands[REG_FIRST].type; 290 | uint8_t access = x86->operands[REG_FIRST].access; 291 | return (type == X86_OP_REG && (access == CS_AC_WRITE || access == CS_AC_READ|CS_AC_WRITE)); 292 | } 293 | 294 | /* 295 | Name: is_dst_mem 296 | Description: this function checks if the destionation is a memory location 297 | */ 298 | bool is_dst_mem(Instruction *current) { 299 | if(!current) return false; 300 | cs_x86 *x86 = current->insn->detail->x86; 301 | uint8_t type = x86->operands[REG_FIRST].type; 302 | uint8_t access = x86->operands[REG_FIRST].access; 303 | return (type == X86_OP_MEM && (access == CS_AC_WRITE || access == CS_AC_READ|CS_AC_WRITE)); 304 | } 305 | 306 | /* 307 | Name: cmp_mnemonic 308 | Description: compares two mnemonics using strncmp and using 309 | the length of the second mnemonic. Returns TRUE is equals. 310 | */ 311 | bool cmp_mnemonic(char *mnemonic1, char *mnemonic2) { 312 | return (strncmp(mnemonic1, mnemonic2, strlen(mnemonic2)) == 0); 313 | } 314 | 315 | /* 316 | Name: cmp_id 317 | Description: compares two IDs, refer to the Capstone cs_insn.id 318 | value. On capstone/x86.h you can find all the available IDs. 319 | */ 320 | bool cmp_id(uint32_t id1, uint32_t id2) { 321 | return (id1 == id2); 322 | } 323 | 324 | /* 325 | Name: print_insn 326 | Description: prints a string representation of the instruction (mnemonic & op_str) 327 | */ 328 | void print_insn(char *msg, Instruction *current) { 329 | printf("%s %s %s\n", msg, current->insn->mnemonic, current->insn->op_str); 330 | } 331 | 332 | /* 333 | Name: print_insn_details 334 | Description: prints a detailed representation of the instruction, with regs/mem/imm info. 335 | */ 336 | void print_insn_details(csh handle, Instruction *current) { 337 | if(!current) return; 338 | uint8_t dst_reg = get_reg_at(current, REG_FIRST); 339 | uint8_t src_reg = get_reg_at(current, REG_SECOND); 340 | uint8_t base = get_base(current); 341 | uint8_t index = get_index(current); 342 | if(is_valid(dst_reg)) printf("REG_FIRST: %s\n", cs_reg_name(handle, dst_reg)); 343 | if(is_valid(src_reg)) printf("REG_SECOND: %s\n", cs_reg_name(handle, src_reg)); 344 | if(is_valid(base)) printf("base: %s\n", cs_reg_name(handle, base)); 345 | if(is_valid(index)) printf("index: %s\n", cs_reg_name(handle, index)); 346 | uint32_t scale; 347 | if(get_scale(current, &scale)) printf("scale: 0x%lx\n", scale); 348 | uint32_t disp; 349 | if(get_disp(current, &disp)) printf("disp: 0x%lx\n", disp); 350 | uint64_t imm; 351 | if(get_imm(current, &imm)) printf("imm: 0x%lx\n", imm); 352 | } 353 | 354 | /* Assemblying & Updating an instruction */ 355 | 356 | bool update_disasm(Instruction *insn, uint64_t address, uint8_t mode) { 357 | csh handle; 358 | size_t count; 359 | if(cs_open(CS_ARCH_X86, mode, &handle) != CS_ERR_OK) { 360 | printf("[-] Error: cs_open, cannot start disassembler.\n"); 361 | return false; 362 | } 363 | cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); 364 | count = cs_disasm(handle, insn->insn->bytes, insn->insn->size, address, 0, &insn->insn); 365 | if(count >= 1) { 366 | } else { 367 | printf("[-] Error: cs_disasm, error while disassembling.\n"); 368 | return false; 369 | } 370 | cs_close(&handle); 371 | return true; 372 | } 373 | 374 | bool reassemble(Instruction *insn, uint8_t mode) { 375 | //checking if "assemble" function is imported 376 | if(!assemble) { 377 | printf("[-] assemble(XEDParse *xedparse) function not found!\n"); 378 | return false; 379 | } 380 | XEDPARSE_STATUS result; 381 | XEDPARSE parse; 382 | switch(mode) { 383 | case CS_MODE_32: 384 | parse.x64 = false; 385 | break; 386 | case CS_MODE_64: 387 | parse.x64 = true; 388 | break; 389 | } 390 | parse.cip = 0; 391 | char instr[256] = ""; 392 | strcat(instr, insn->insn->mnemonic); 393 | strcat(instr, " "); 394 | strcat(instr, insn->insn->op_str); 395 | instr[strlen(instr)] = 0; 396 | strcpy(parse.instr, instr); 397 | result = assemble(&parse); 398 | //result = XEDParseAssemble(&parse); 399 | if(result == XEDPARSE_ERROR) { 400 | if(VERBOSE_ERROR) 401 | printf("[!] Error: \"%s\" while assembling \"%s\"\n", parse.error, parse.instr); 402 | return false; 403 | } 404 | insn->insn->size = parse.dest_size; 405 | memcpy(insn->insn->bytes, parse.dest, parse.dest_size); 406 | return result; 407 | } 408 | 409 | Instruction *assemble_insn(char *mnemonic, char *op_str, uint64_t address, uint8_t mode) { 410 | Instruction *new_insn = calloc(1, sizeof(Instruction)); 411 | new_insn->insn = calloc(1, sizeof(cs_insn)); 412 | sprintf(new_insn->insn->mnemonic, mnemonic); 413 | sprintf(new_insn->insn->op_str, op_str); 414 | if(!(reassemble(new_insn, mode) && update_disasm(new_insn, address, mode))) { 415 | free(new_insn->insn); 416 | free(new_insn); 417 | return NULL; 418 | } else { 419 | return new_insn; 420 | } 421 | } 422 | 423 | Instruction *assemble_fake_insn(char *mnemonic, char *original_op_str, char *fake_op_str, uint64_t address, uint8_t mode) { 424 | Instruction *new_insn = assemble_insn(mnemonic, original_op_str, address, mode); 425 | if(new_insn) { 426 | //copy fake op_str 427 | sprintf(new_insn->insn->op_str, fake_op_str); 428 | //convert the instruction bytes to NOPs 429 | memset(new_insn->insn->bytes, 0x90, new_insn->insn->size); 430 | //mark the instruction as invalid 431 | new_insn->invalid = true; 432 | return new_insn; 433 | } else { 434 | return NULL; 435 | } 436 | } 437 | 438 | /* Instruction search & access flags */ 439 | 440 | /* 441 | Name: find_insn 442 | Description: this function is used to find an Instruction matching the "pattern details" passed using InsnMatch. 443 | */ 444 | ListEntry *find_insn(ListEntry *start, ListEntry *end, InsnMatch *insn) { 445 | //check if the start is invalid 446 | if(!start) return NULL; 447 | //check if start is before end 448 | ListEntry *temp = start; 449 | if(ListIsBefore(start, end) != start) return NULL; 450 | //start searching the pattern instruction 451 | ListEntry *result, *current = start; 452 | //Capstone variables 453 | cs_x86 *x86; 454 | cs_x86_op *op; 455 | size_t op_count; 456 | //Temporary variables for operands 457 | Instruction *instruction; 458 | while(current && current != end) { 459 | //get Instruction from ListEntry 460 | instruction = (Instruction *)current->content; 461 | //check instruction and instruction->insn 462 | if(!instruction || !instruction->insn) { 463 | printf("[!] Error with find_insn!\n"); 464 | ExitProcess(EXIT_FAILURE); 465 | } 466 | //first check the mnemonic 467 | if(cmp_id(instruction->insn->id, insn->id)) { 468 | //printf("checking current: %s %s\n", instruction->insn->mnemonic, instruction->insn->op_str); 469 | InsnMatch insn_l = {}; 470 | //extract operands from the instructions 471 | x86 = &(instruction->insn->detail->x86); 472 | op_count = x86->op_count; 473 | for(size_t i = 0; i < op_count; i++) { 474 | op = &(x86->operands[i]); 475 | switch(op->type) { 476 | case X86_OP_REG: 477 | if(i == 0) { 478 | insn_l.dst_reg = op->reg; 479 | } else { 480 | insn_l.src_reg = op->reg; 481 | } 482 | break; 483 | case X86_OP_MEM: 484 | insn_l.mem.base = op->mem.base; 485 | insn_l.mem.index = op->mem.index; 486 | insn_l.mem.scale = (uint32_t)op->mem.scale; 487 | insn_l.mem.disp = (uint32_t)op->mem.disp; 488 | break; 489 | case X86_OP_IMM: 490 | insn_l.src_imm = op->imm; 491 | break; 492 | } 493 | } 494 | //determine current instruction InsnType 495 | uint8_t dst_type = x86->operands[0].type, src_type = x86->operands[1].type; 496 | if(dst_type == X86_OP_REG) { 497 | switch(src_type) { 498 | case X86_OP_REG: 499 | insn_l.type = X86_DST_REG_SRC_REG; 500 | break; 501 | case X86_OP_MEM: 502 | insn_l.type = X86_DST_REG_SRC_MEM; 503 | break; 504 | case X86_OP_IMM: 505 | insn_l.type = X86_DST_REG_SRC_IMM; 506 | break; 507 | default: 508 | insn_l.type = X86_DST_REG; 509 | break; 510 | } 511 | } else if(dst_type == X86_OP_MEM) { 512 | switch(src_type) { 513 | case X86_OP_REG: 514 | insn_l.type = X86_DST_MEM_SRC_REG; 515 | break; 516 | case X86_OP_IMM: 517 | insn_l.type = X86_DST_MEM_SRC_IMM; 518 | break; 519 | default: 520 | insn_l.type = X86_DST_MEM; 521 | break; 522 | } 523 | } else if(dst_type == X86_OP_IMM) { 524 | insn_l.type = X86_DST_IMM; 525 | } else { 526 | insn_l.type = X86_NO_OP; 527 | } 528 | //check for general or specific match 529 | if(!insn->specific_match) { 530 | //printf("insn_l.type (%d) == (%d) insn->type\n", insn_l.type, insn->type); 531 | if(insn_l.type == insn->type) return current; 532 | } else { 533 | //check if the operands are the right ones 534 | switch(insn->type) { 535 | case X86_DST_REG_SRC_REG: 536 | if((insn->wildcard_dst_reg || insn_l.dst_reg == insn->dst_reg) && (insn->wildcard_src_reg || insn_l.src_reg == insn->src_reg)) return current; 537 | break; 538 | case X86_DST_REG_SRC_MEM: 539 | if((insn->wildcard_dst_reg || insn_l.dst_reg == insn->dst_reg) && (insn->wildcard_mem || (insn_l.mem.base == insn->mem.base && insn_l.mem.index == insn->mem.index && insn_l.mem.scale == insn->mem.scale && insn_l.mem.disp == insn->mem.disp))) return current; 540 | break; 541 | case X86_DST_REG_SRC_IMM: 542 | if((insn->wildcard_dst_reg || insn_l.dst_reg == insn->dst_reg) && (insn->wildcard_imm || insn_l.src_imm == insn->src_imm)) return current; 543 | break; 544 | case X86_DST_MEM_SRC_REG: 545 | if((insn->wildcard_mem || (insn_l.mem.base == insn->mem.base && insn_l.mem.index == insn->mem.index && insn_l.mem.scale == insn->mem.scale && insn_l.mem.disp == insn->mem.disp)) && (insn->wildcard_src_reg || insn_l.src_reg == insn->src_reg)) return current; 546 | break; 547 | case X86_DST_MEM_SRC_IMM: 548 | if((insn->wildcard_mem || (insn_l.mem.base == insn->mem.base && insn_l.mem.index == insn->mem.index && insn_l.mem.scale == insn->mem.scale && insn_l.mem.disp == insn->mem.disp)) && (insn->wildcard_imm || insn_l.src_imm == insn->src_imm)) return current; 549 | break; 550 | case X86_DST_REG: 551 | if(insn->wildcard_dst_reg || insn_l.dst_reg == insn->dst_reg) return current; 552 | break; 553 | case X86_DST_MEM: 554 | if(insn->wildcard_mem || (insn_l.mem.base == insn->mem.base && insn_l.mem.index == insn->mem.index && insn_l.mem.scale == insn->mem.scale && insn_l.mem.disp == insn->mem.disp)) return current; 555 | break; 556 | case X86_NO_OP: 557 | return current; 558 | break; 559 | } 560 | } 561 | } 562 | //pass to the next instruction 563 | current = current->next; 564 | } 565 | return NULL; 566 | } 567 | 568 | /* 569 | Name: find_insn_op_access 570 | Description: this function is used to find out what instruction accesses REG or MEM in a certain way (READ - WRITE - READ|WRITE). 571 | The specific flag is used to check if the access is general or a specific type (READ - WRITE - READ|WRITE). 572 | */ 573 | ListEntry *find_insn_op_access(ListEntry *start, ListEntry *end, InsnAccess *acc) { 574 | //check if start is valid 575 | if(!start) return NULL; 576 | //check if start is before end 577 | if(ListIsBefore(start, end) != start) return NULL; 578 | ListEntry *current = start; 579 | //Capstone variables 580 | cs_x86 *x86; 581 | cs_x86_op *op; 582 | size_t op_count; 583 | //Useful variables 584 | Instruction *insn; 585 | while(current && current != end) { 586 | //extract Instruction from ListEntry 587 | insn = (Instruction *)current->content; 588 | //check if InsnAccess is found 589 | x86 = &(insn->insn->detail->x86); 590 | op_count = x86->op_count; 591 | for(size_t i = 0; i < op_count; i++) { 592 | op = &(x86->operands[i]); 593 | switch(op->type) { 594 | case X86_OP_REG: 595 | if(op->access == acc->access_type && op->type == acc->op_type) { 596 | if(acc->same_reg) { 597 | if(op->reg == acc->reg) return current; 598 | } else { 599 | if(is_same_register_type(op->reg, acc->reg)) return current; 600 | } 601 | } 602 | break; 603 | case X86_OP_MEM: 604 | if(acc->op_type == X86_OP_MEM) { 605 | if(op->mem.base == acc->mem.base && op->mem.index == acc->mem.index && (uint32_t)op->mem.scale == acc->mem.scale && (uint32_t)op->mem.disp == acc->mem.disp) { 606 | if(op->access == acc->access_type) return current; 607 | } 608 | } else if(acc->op_type == X86_OP_REG) { 609 | if(acc->same_reg) { 610 | if(acc->access_type == CS_AC_READ && (op->mem.base == acc->reg || op->mem.index == acc->reg)) return current; 611 | } else { 612 | if(acc->access_type == CS_AC_READ && (is_same_register_type(op->mem.base, acc->reg) || is_same_register_type(op->mem.index, acc->reg))) return current; 613 | } 614 | } 615 | break; 616 | } 617 | } 618 | current = current->next; 619 | } 620 | return NULL; 621 | } 622 | 623 | /* 624 | Name: find_insn_op_general_access 625 | Description: This function is used to find the first general access to REG or MEM; with general access is indicated 626 | the first READ or WRITE or READ|WRITE operation accessing REG or MEM. 627 | */ 628 | 629 | ListEntry *find_insn_op_general_access(ListEntry *start, ListEntry *end, InsnAccess *acc) { 630 | if(start == NULL) return NULL; 631 | //if(VERBOSE && start) print_insn("[I] start: ", start->content); 632 | //if(VERBOSE && end) print_insn("[I] end: ", end->content); 633 | acc->access_type = CS_AC_WRITE; 634 | ListEntry *write_only = find_insn_op_access(start, end, acc); 635 | acc->access_type = CS_AC_READ; 636 | ListEntry *read_only = find_insn_op_access(start, end, acc); 637 | acc->access_type = CS_AC_READ|CS_AC_WRITE; 638 | ListEntry *read_or_write = find_insn_op_access(start, end, acc); 639 | //if(VERBOSE && write_only) print_insn("[I] write_only: ", write_only->content); 640 | //if(VERBOSE && read_only) print_insn("[I] read_only: ", read_only->content); 641 | //if(VERBOSE && read_or_write) print_insn("[I] read_or_write: ", read_or_write->content); 642 | ListEntry *first = ListIsBefore(write_only, read_only); 643 | first = ListIsBefore(first, read_or_write); 644 | //if(VERBOSE && first) print_insn("[I] find_insn_op_general_access: ", first->content); 645 | return first; 646 | } 647 | 648 | /* Instruction updating functions */ 649 | 650 | bool is_strange_reg(uint8_t reg) { 651 | //this is an array of registers that cannot be directly used in an instruction 652 | uint8_t strange_reg[1] = { X86_REG_EFLAGS }; 653 | for(size_t i = 0; i < 1; i++) { 654 | if(reg == strange_reg[i]) { 655 | return true; 656 | } 657 | } 658 | return false; 659 | } 660 | 661 | //--------------------------------------------------------------------------------------------------------------------------------- 662 | 663 | /* 664 | Name: prettify_mem 665 | Description: this function is useless, it will fix the op_str of an invalid memory instruction just to make 666 | it easier to read. 667 | */ 668 | /*char *prettify_mem(csh handle, uint8_t base, uint8_t index, uint32_t scale, uint32_t disp, uint8_t src_reg, uint8_t dst_reg, uint8_t size) { 669 | //remember to free it when unused 670 | char *pretty_op_str = calloc(0xFF, sizeof(char)); 671 | //fix memory part 672 | char *base_s = (is_valid(base)) ? cs_reg_name(handle, base) : ""; 673 | char *index_s = (is_valid(index)) ? cs_reg_name(handle, index) : ""; 674 | char *scale_s = calloc(10, sizeof(char)); 675 | char *disp_s = calloc(10, sizeof(char)); 676 | char *mem_size = get_mem_indicator(size); 677 | if(scale != 1) sprintf(scale, " * 0x%lx", scale); 678 | if(disp != 0) sprintf(disp, " + 0x%lx", disp); 679 | //generate full op_str 680 | if(is_valid(dst_reg)) { 681 | sprintf(pretty_op_str, "%s, %s ptr [%s%s%s%s]", cs_reg_name(handle, dst_reg), mem_size, base_s, index_s, scale_s, disp_s); 682 | } else if(is_valid(src_reg)) { 683 | sprintf(pretty_op_str, "%s ptr [%s%s%s%s], %s", mem_size, base_s, index_s, scale_s, disp_s, cs_reg_name(handle, src_reg)); 684 | } 685 | return pretty_op_str; 686 | }*/ 687 | 688 | /* 689 | Name: update_insn_str 690 | Description: this function tries to generate a valid Instruction representation of an updated instruction. 691 | It extracts all the information, understand what the instruction looks like and assemble the new one. 692 | The main limitation is that it can handle only 0/1/2 operands instructions, maybe in the future, if needed, 693 | it will be updated. 694 | */ 695 | Instruction *update_insn_str(csh handle, Instruction *old_insn, uint8_t mode) { 696 | if(!old_insn) return NULL; 697 | //extract operands count 698 | uint8_t op_count = get_op_count(old_insn); 699 | //check op_count < 3 700 | if(op_count > 2) { 701 | printf("[!] Error, op_count > 2 not supported!\n"); 702 | ExitProcess(EXIT_FAILURE); 703 | return NULL; 704 | } 705 | //extract registers information 706 | uint8_t dst_reg = get_reg_at(old_insn, REG_FIRST); 707 | uint8_t src_reg = get_reg_at(old_insn, REG_SECOND); 708 | //check if source or destination registers are strange 709 | bool dst_reg_strange = is_strange_reg(dst_reg); 710 | bool src_reg_strange = is_strange_reg(src_reg); 711 | //extract memory information 712 | uint8_t size; 713 | bool size_found = get_mem_size(old_insn, &size); 714 | uint8_t base = get_base(old_insn); 715 | uint8_t index = get_index(old_insn); 716 | uint32_t scale, disp; 717 | get_scale(old_insn, &scale); 718 | get_disp(old_insn, &disp); 719 | uint64_t imm; 720 | bool imm_found = get_imm(old_insn, &imm); 721 | //generate the mnemonic using id 722 | char *mnemonic = (char *)cs_insn_name(handle, old_insn->insn->id); 723 | //generate the op_str using the extracted information 724 | char *op_str = calloc(0xFF, sizeof(char)); 725 | char *fake_op_str = (dst_reg_strange || src_reg_strange) ? calloc(0xFF, sizeof(char)) : NULL; 726 | if(op_count == 0) { 727 | //the instruction is made up only by the mnemonic, so it is X86_NO_OP 728 | } if(is_memory_insn(old_insn)) { 729 | //generate the memory size indicator string 730 | char *indicator = (size_found) ? get_mem_indicator(size) : ""; 731 | if(is_valid(dst_reg)) { 732 | //check if it is X86_DST_REG_SRC_MEM 733 | if(dst_reg_strange) { 734 | uint8_t fake_reg = (mode == CS_MODE_32) ? X86_REG_EAX : X86_REG_RAX; 735 | sprintf(op_str, "%s, %s [%s + %s * 0x%lx + 0x%lx]", cs_reg_name(handle, fake_reg), indicator, cs_reg_name(handle, base), cs_reg_name(handle, index), scale, disp); 736 | sprintf(fake_op_str, "%s, %s [%s + %s * 0x%lx + 0x%lx]", cs_reg_name(handle, dst_reg), indicator, cs_reg_name(handle, base), cs_reg_name(handle, index), scale, disp); 737 | } else { 738 | sprintf(op_str, "%s, %s [%s + %s * 0x%lx + 0x%lx]", cs_reg_name(handle, dst_reg), indicator, cs_reg_name(handle, base), cs_reg_name(handle, index), scale, disp); 739 | } 740 | } else if(is_valid(src_reg)) { 741 | //check if it is X86_DST_MEM_SRC_REG 742 | if(src_reg_strange) { 743 | uint8_t fake_reg = (mode == CS_MODE_32) ? X86_REG_EAX : X86_REG_RAX; 744 | sprintf(op_str, "%s [%s + %s * 0x%lx + 0x%lx], %s", indicator, cs_reg_name(handle, base), cs_reg_name(handle, index), scale, disp, cs_reg_name(handle, fake_reg)); 745 | sprintf(fake_op_str, "%s [%s + %s * 0x%lx + 0x%lx], %s", indicator, cs_reg_name(handle, base), cs_reg_name(handle, index), scale, disp, cs_reg_name(handle, src_reg)); 746 | } else { 747 | sprintf(op_str, "%s [%s + %s * 0x%lx + 0x%lx], %s", indicator, cs_reg_name(handle, base), cs_reg_name(handle, index), scale, disp, cs_reg_name(handle, src_reg)); 748 | } 749 | } else if(imm_found) { 750 | //check if it is X86_DST_MEM_SRC_IMM 751 | sprintf(op_str, "%s [%s + %s * 0x%lx + 0x%lx], 0x%llx", indicator, cs_reg_name(handle, base), cs_reg_name(handle, index), scale, disp, imm); 752 | } else if(op_count == 1) { 753 | //check if it is X86_DST_MEM 754 | sprintf(op_str, "%s [%s + %s * 0x%lx + 0x%lx]", indicator, cs_reg_name(handle, base), cs_reg_name(handle, index), scale, disp); 755 | } 756 | } else { 757 | if(is_valid(src_reg) && is_valid(dst_reg)) { 758 | //check if it is X86_DST_REG_SRC_REG 759 | if(src_reg_strange) { 760 | uint8_t fake_reg = (mode == CS_MODE_32) ? X86_REG_EAX : X86_REG_RAX; 761 | sprintf(op_str, "%s, %s", cs_reg_name(handle, fake_reg), cs_reg_name(handle, fake_reg)); 762 | sprintf(fake_op_str, "%s, %s", cs_reg_name(handle, dst_reg), cs_reg_name(handle, src_reg)); 763 | } else if(dst_reg_strange) { 764 | uint8_t fake_reg = (mode == CS_MODE_32) ? X86_REG_EAX : X86_REG_RAX; 765 | sprintf(op_str, "%s, %s", cs_reg_name(handle, fake_reg), cs_reg_name(handle, src_reg)); 766 | sprintf(fake_op_str, "%s, %s", cs_reg_name(handle, dst_reg), cs_reg_name(handle, src_reg)); 767 | } else { 768 | sprintf(op_str, "%s, %s", cs_reg_name(handle, dst_reg), cs_reg_name(handle, src_reg)); 769 | } 770 | } else if(is_valid(dst_reg) && imm_found) { 771 | //check if it is X86_DST_REG_SRC_IMM 772 | if(dst_reg_strange) { 773 | uint8_t fake_reg = (mode == CS_MODE_32) ? X86_REG_EAX : X86_REG_RAX; 774 | sprintf(op_str, "%s, 0x%llx", cs_reg_name(handle, fake_reg), imm); 775 | sprintf(fake_op_str, "%s, 0x%llx", cs_reg_name(handle, dst_reg), imm); 776 | } else { 777 | sprintf(op_str, "%s, 0x%llx", cs_reg_name(handle, dst_reg), imm); 778 | } 779 | } else if(op_count == 1) { 780 | //check if it is X86_DST_REG 781 | sprintf(op_str, "%s", cs_reg_name(handle, dst_reg)); 782 | } 783 | } 784 | //assemble new instruction 785 | Instruction *new_insn = assemble_insn(mnemonic, op_str, old_insn->insn->address, mode); 786 | //check if the instruction was invalid 787 | if(old_insn->invalid) { 788 | //fix op_str 789 | sprintf(new_insn->insn->op_str, fake_op_str); 790 | //fix registers 791 | if(dst_reg_strange) { 792 | set_reg_at(new_insn, REG_FIRST, dst_reg); 793 | } else if(src_reg_strange) { 794 | set_reg_at(new_insn, REG_SECOND, src_reg); 795 | } else { 796 | printf("[!] Error while assembling the INVALID instruction!\n"); 797 | ExitProcess(EXIT_FAILURE); 798 | return NULL; 799 | } 800 | } 801 | /*if(VERBOSE && new_insn) { 802 | print_insn("[I] Updated instruction: ", new_insn); 803 | //print_insn_details(handle, new_insn); 804 | }*/ 805 | if(!new_insn) { 806 | printf("[!] Error while assembling the instruction!\n"); 807 | ExitProcess(EXIT_FAILURE); 808 | } 809 | //free space 810 | //free(mnemonic); 811 | //free(op_str); 812 | return new_insn; 813 | } -------------------------------------------------------------------------------- /Rewrite/deob/list.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Double Linked List Definition */ 4 | 5 | typedef struct ListEntry { 6 | struct ListEntry *next; 7 | struct ListEntry *prev; 8 | void *content; 9 | } ListEntry; 10 | 11 | typedef struct List { 12 | uint32_t entry_count; 13 | ListEntry *first; 14 | ListEntry *last; 15 | } List; 16 | 17 | /* Double Linked List Implementation */ 18 | 19 | ListEntry *ListEntryCreate(void *content) { 20 | //remember to free it when unused 21 | ListEntry *new_entry = calloc(1, sizeof(ListEntry)); 22 | new_entry->content = content; 23 | return new_entry; 24 | } 25 | 26 | List *ListCreate() { 27 | //remember to free it when unused 28 | return calloc(1, sizeof(List)); 29 | } 30 | 31 | void ListDestroy(List *list) { 32 | ListEntry *current = list->first; 33 | while(current != NULL) { 34 | free(current->content); 35 | current = current->next; 36 | } 37 | free(current); 38 | free(list->first); 39 | free(list->last); 40 | //free(list); 41 | } 42 | 43 | void ListInsertAfter(List *list, ListEntry *old_entry, ListEntry *new_entry) { 44 | if(!new_entry) return; 45 | if(old_entry) { 46 | //Next old entry update 47 | ListEntry *next = old_entry->next; 48 | if(next != NULL) { 49 | next->prev = new_entry; 50 | } 51 | //Update new_entry prev & next 52 | new_entry->prev = old_entry; 53 | new_entry->next = next; 54 | //Update old_entry next 55 | old_entry->next = new_entry; 56 | if(list->last == old_entry) { 57 | list->last = new_entry; 58 | } 59 | //increment List size 60 | list->entry_count++; 61 | } 62 | } 63 | 64 | void ListInsertBefore(List *list, ListEntry *old_entry, ListEntry *new_entry) { 65 | if(old_entry) { 66 | //Next old instruction update 67 | ListEntry *prev = old_entry->prev; 68 | prev->next = new_entry; 69 | //Update new_entry prev & next 70 | new_entry->prev = prev; 71 | new_entry->next = old_entry; 72 | //Update old_entry next 73 | old_entry->prev = new_entry; 74 | if(list->first == old_entry) { 75 | list->first = new_entry; 76 | } 77 | //increment List size 78 | list->entry_count++; 79 | } 80 | } 81 | 82 | void ListPush(List *list, ListEntry *new_entry) { 83 | if(!(list->last)) { 84 | list->first = new_entry; 85 | list->last = new_entry; 86 | } else { 87 | list->last->next = new_entry; 88 | new_entry->prev = list->last; 89 | list->last = new_entry; 90 | } 91 | //increment List size 92 | list->entry_count++; 93 | } 94 | 95 | bool ListEntrySetNext(ListEntry *current, ListEntry *next) { 96 | if(!current) return false; 97 | current->next = next; 98 | return true; 99 | } 100 | 101 | bool ListEntrySetPrev(ListEntry *current, ListEntry *prev) { 102 | if(!current) return false; 103 | current->prev = prev; 104 | return true; 105 | } 106 | 107 | void ListRemove(List *list, ListEntry *old_entry) { 108 | if(!old_entry) return; 109 | if(list->first == old_entry) { 110 | list->first = old_entry->next; 111 | } 112 | if(list->last == old_entry) { 113 | list->last = old_entry->prev; 114 | } 115 | if(old_entry->prev) { 116 | old_entry->prev->next = old_entry->next; 117 | } 118 | if(old_entry->next) { 119 | old_entry->next->prev = old_entry->prev; 120 | } 121 | //free(old_entry); 122 | } 123 | 124 | void *ListPop(List *list) { 125 | if(!list) return NULL; 126 | if(list->entry_count == 0) return NULL; 127 | //remember to free the popped_entry somewhere 128 | void *popped_entry = list->first; 129 | ListRemove(list, popped_entry); 130 | //decrement list size 131 | list->entry_count--; 132 | return popped_entry; 133 | } 134 | 135 | bool ListCmpEntries(ListEntry *e1, ListEntry *e2, size_t n) { 136 | return (memcmp(e1->content, e2->content, n) == 0) ? true : false; 137 | } 138 | 139 | /* Information functions */ 140 | 141 | uint32_t ListNumEntry(List *list) { 142 | return list->entry_count; 143 | } 144 | 145 | bool ListIsEmpty(List *list) { 146 | return (bool)list->entry_count; 147 | } 148 | 149 | ListEntry *ListIsBefore(ListEntry *first, ListEntry *second) { 150 | if(!first && !second) return NULL; 151 | if(!first && second) return second; 152 | if(first && !second) return first; 153 | //check if "first" is encountered before "second" 154 | ListEntry *temp = first; 155 | while(temp) { 156 | if(temp == second) return first; 157 | temp = temp->next; 158 | } 159 | return second; 160 | } 161 | 162 | void ListChangeEntry(ListEntry *entry, void *new_content) { 163 | //delete old content 164 | free(entry->content); 165 | //assign new content 166 | entry->content = new_content; 167 | } 168 | 169 | /* Useful debug functions */ 170 | 171 | void print_disassembly(csh handle, List *list, bool advanced) { 172 | cs_x86 *x86; 173 | cs_x86_op *op; 174 | size_t op_count = 0; 175 | size_t counter = 0; 176 | ListEntry *entry = list->first; 177 | Instruction *current; 178 | while(entry) { 179 | //extract Instruction from the current ListEntry 180 | current = (Instruction *)entry->content; 181 | if(advanced) { 182 | printf("0x%llx %s %s (invalid: %d)\n", current->insn->address, current->insn->mnemonic, current->insn->op_str, current->invalid); 183 | } else { 184 | if(SHOW_ADDR) { 185 | printf("0x%llx %s %s\n", current->insn->address, current->insn->mnemonic, current->insn->op_str); 186 | } else { 187 | printf("%s %s\n", current->insn->mnemonic, current->insn->op_str); 188 | } 189 | } 190 | if(advanced /*&& !current->invalid*/) { 191 | x86 = &(current->insn->detail->x86); 192 | op_count = x86->op_count; 193 | for(size_t i = 0; i < op_count; i++) { 194 | op = &(x86->operands[i]); 195 | switch(op->access) { 196 | case CS_AC_READ: 197 | printf("\t\tCS_AC_READ (%d)\n", op->access); 198 | break; 199 | case CS_AC_WRITE: 200 | printf("\t\tCS_AC_WRITE (%d)\n", op->access); 201 | break; 202 | case CS_AC_READ|CS_AC_WRITE: 203 | printf("\t\tCS_AC_READ|CS_AC_WRITE (%d)\n", op->access); 204 | break; 205 | default: 206 | printf("\t\tUNKNOWN (%d)\n", op->access); 207 | break; 208 | } 209 | switch((int)op->type) { 210 | case X86_OP_REG: 211 | printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg)); 212 | break; 213 | case X86_OP_IMM: 214 | printf("\t\toperands[%u].type: IMM = 0x%llx\n", i, op->imm); 215 | printf("\t\toperands[%u].size: IMM.size = 0x%llx\n", i, op->size); 216 | break; 217 | case X86_OP_FP: 218 | printf("\t\toperands[%u].type: FP = %f\n", i, op->fp); 219 | break; 220 | case X86_OP_MEM: 221 | printf("\t\toperands[%u].type: MEM\n", i); 222 | if (op->mem.segment != X86_REG_INVALID) 223 | printf("\t\t\toperands[%u].mem.segment: REG = %s\n", i, cs_reg_name(handle, op->mem.segment)); 224 | if (op->mem.base != X86_REG_INVALID) 225 | printf("\t\t\toperands[%u].mem.base: REG = %s\n", i, cs_reg_name(handle, op->mem.base)); 226 | if (op->mem.index != X86_REG_INVALID) 227 | printf("\t\t\toperands[%u].mem.index: REG = %s\n", i, cs_reg_name(handle, op->mem.index)); 228 | if (op->mem.scale != 1) 229 | printf("\t\t\toperands[%u].mem.scale: %u\n", i, op->mem.scale); 230 | if (op->mem.disp != 0) 231 | printf("\t\t\toperands[%u].mem.disp: 0x%llx\n", i, op->mem.disp); 232 | break; 233 | default: 234 | break; 235 | } 236 | } 237 | if(current->insn->detail->regs_write_count > 0) { 238 | printf("[REG WRITE]: "); 239 | for(size_t i = 0; i < current->insn->detail->regs_write_count; i++) { 240 | printf("(%s)", cs_reg_name(handle, current->insn->detail->regs_write[i])); 241 | } 242 | } 243 | if(current->insn->detail->regs_read_count > 0) { 244 | printf("\n[REG READ]: "); 245 | for(size_t i = 0; i < current->insn->detail->regs_read_count; i++) { 246 | printf("(%s)", cs_reg_name(handle, current->insn->detail->regs_read[i])); 247 | } 248 | } 249 | printf("\n[HEX]: "); 250 | for(size_t i = 0; i < current->insn->size; i++) { 251 | printf("%02x ", current->insn->bytes[i]); 252 | } 253 | printf("\n"); 254 | } 255 | entry = entry->next; 256 | } 257 | } 258 | 259 | void print_memory_value(List *list) { 260 | if(!list) return; 261 | MemoryValue *mem_val; 262 | ListEntry *entry = list->first; 263 | while(entry) { 264 | mem_val = (MemoryValue *)entry->content; 265 | printf("MemoryValue { address = 0x%llx, size = 0x%x, value = 0x%llx }\n", mem_val->address, mem_val->size, mem_val->value); 266 | entry = entry->next; 267 | } 268 | } -------------------------------------------------------------------------------- /Rewrite/deob/op_utility.h: -------------------------------------------------------------------------------- 1 | uint8_t register_type(uint8_t reg) { 2 | uint8_t register_type = -1, register_code = 0x60; 3 | /* 4 | register_code: 5 | 6 | RAX = 0x50 7 | EAX = 0x40 8 | AX = 0x30 9 | AH = 0x20 10 | AL = 0x10 11 | */ 12 | /* 13 | register_type: 14 | 15 | RAX = 0x0 16 | RBX = 0x1 17 | RCX = 0x2 18 | RDX = 0x3 19 | RSP = 0x4 20 | RBP = 0x5 21 | RSI = 0x6 22 | RDI = 0x7 23 | R8 = 0x8 24 | R9 = 0x9 25 | R10 = 0xa 26 | R11 = 0xb 27 | R12 = 0xc 28 | R13 = 0xd 29 | R14 = 0xe 30 | R15 = 0xf 31 | */ 32 | switch(reg) { 33 | case X86_REG_AL: 34 | register_code -= 0x10; 35 | case X86_REG_AH: 36 | register_code -= 0x10; 37 | case X86_REG_AX: 38 | register_code -= 0x10; 39 | case X86_REG_EAX: 40 | register_code -= 0x10; 41 | case X86_REG_RAX: 42 | register_code -= 0x10; 43 | register_type = 0x0; 44 | break; 45 | case X86_REG_BL: 46 | register_code -= 0x10; 47 | case X86_REG_BH: 48 | register_code -= 0x10; 49 | case X86_REG_BX: 50 | register_code -= 0x10; 51 | case X86_REG_EBX: 52 | register_code -= 0x10; 53 | case X86_REG_RBX: 54 | register_code -= 0x10; 55 | register_type = 0x1; 56 | break; 57 | case X86_REG_CL: 58 | register_code -= 0x10; 59 | case X86_REG_CH: 60 | register_code -= 0x10; 61 | case X86_REG_CX: 62 | register_code -= 0x10; 63 | case X86_REG_ECX: 64 | register_code -= 0x10; 65 | case X86_REG_RCX: 66 | register_code -= 0x10; 67 | register_type = 0x2; 68 | break; 69 | case X86_REG_DL: 70 | register_code -= 0x10; 71 | case X86_REG_DH: 72 | register_code -= 0x10; 73 | case X86_REG_DX: 74 | register_code -= 0x10; 75 | case X86_REG_EDX: 76 | register_code -= 0x10; 77 | case X86_REG_RDX: 78 | register_code -= 0x10; 79 | register_type = 0x3; 80 | break; 81 | case X86_REG_SPL: 82 | register_code -= 0x10; 83 | case X86_REG_SP: 84 | register_code -= 0x10; 85 | case X86_REG_ESP: 86 | register_code -= 0x10; 87 | case X86_REG_RSP: 88 | register_code -= 0x10; 89 | register_type = 0x4; 90 | break; 91 | case X86_REG_BPL: 92 | register_code -= 0x10; 93 | case X86_REG_BP: 94 | register_code -= 0x10; 95 | case X86_REG_EBP: 96 | register_code -= 0x10; 97 | case X86_REG_RBP: 98 | register_code -= 0x10; 99 | register_type = 0x5; 100 | break; 101 | case X86_REG_SIL: 102 | register_code -= 0x10; 103 | case X86_REG_SI: 104 | register_code -= 0x10; 105 | case X86_REG_ESI: 106 | register_code -= 0x10; 107 | case X86_REG_RSI: 108 | register_code -= 0x10; 109 | register_type = 0x6; 110 | break; 111 | case X86_REG_DIL: 112 | register_code -= 0x10; 113 | case X86_REG_DI: 114 | register_code -= 0x10; 115 | case X86_REG_EDI: 116 | register_code -= 0x10; 117 | case X86_REG_RDI: 118 | register_code -= 0x10; 119 | register_type = 0x7; 120 | break; 121 | case X86_REG_R8B: 122 | register_code -= 0x20; 123 | case X86_REG_R8W: 124 | register_code -= 0x10; 125 | case X86_REG_R8D: 126 | register_code -= 0x10; 127 | case X86_REG_R8: 128 | register_code -= 0x10; 129 | register_type = 0x8; 130 | break; 131 | case X86_REG_R9B: 132 | register_code -= 0x20; 133 | case X86_REG_R9W: 134 | register_code -= 0x10; 135 | case X86_REG_R9D: 136 | register_code -= 0x10; 137 | case X86_REG_R9: 138 | register_code -= 0x10; 139 | register_type = 0x9; 140 | break; 141 | case X86_REG_R10B: 142 | register_code -= 0x20; 143 | case X86_REG_R10W: 144 | register_code -= 0x10; 145 | case X86_REG_R10D: 146 | register_code -= 0x10; 147 | case X86_REG_R10: 148 | register_code -= 0x10; 149 | register_type = 0xa; 150 | break; 151 | case X86_REG_R11B: 152 | register_code -= 0x20; 153 | case X86_REG_R11W: 154 | register_code -= 0x10; 155 | case X86_REG_R11D: 156 | register_code -= 0x10; 157 | case X86_REG_R11: 158 | register_code -= 0x10; 159 | register_type = 0xb; 160 | break; 161 | case X86_REG_R12B: 162 | register_code -= 0x20; 163 | case X86_REG_R12W: 164 | register_code -= 0x10; 165 | case X86_REG_R12D: 166 | register_code -= 0x10; 167 | case X86_REG_R12: 168 | register_code -= 0x10; 169 | register_type = 0xc; 170 | break; 171 | case X86_REG_R13B: 172 | register_code -= 0x20; 173 | case X86_REG_R13W: 174 | register_code -= 0x10; 175 | case X86_REG_R13D: 176 | register_code -= 0x10; 177 | case X86_REG_R13: 178 | register_code -= 0x10; 179 | register_type = 0xd; 180 | break; 181 | case X86_REG_R14B: 182 | register_code -= 0x20; 183 | case X86_REG_R14W: 184 | register_code -= 0x10; 185 | case X86_REG_R14D: 186 | register_code -= 0x10; 187 | case X86_REG_R14: 188 | register_code -= 0x10; 189 | register_type = 0xe; 190 | break; 191 | case X86_REG_R15B: 192 | register_code -= 0x20; 193 | case X86_REG_R15W: 194 | register_code -= 0x10; 195 | case X86_REG_R15D: 196 | register_code -= 0x10; 197 | case X86_REG_R15: 198 | register_code -= 0x10; 199 | register_type = 0xf; 200 | break; 201 | //handle EFLAGS + others 202 | case X86_REG_EFLAGS: 203 | register_code = 0xf; 204 | register_type = 0xf; 205 | default: 206 | break; 207 | } 208 | return (register_code | register_type); 209 | } 210 | 211 | uint8_t register_from_code(uint8_t code_type) { 212 | uint8_t type = code_type & 0xF, code = code_type & 0xF0, reg = X86_REG_INVALID; 213 | //printf("type: 0x%llx\n", type); 214 | //printf("code: 0x%llx\n", code); 215 | /* 216 | register_code: 217 | 218 | RAX = 0x50 219 | EAX = 0x40 220 | AX = 0x30 221 | AH = 0x20 222 | AL = 0x10 223 | */ 224 | /* 225 | register_type: 226 | 227 | RAX = 0x0 228 | RBX = 0x1 229 | RCX = 0x2 230 | RDX = 0x3 231 | RSP = 0x4 232 | RBP = 0x5 233 | RSI = 0x6 234 | RDI = 0x7 235 | R8 = 0x8 236 | R9 = 0x9 237 | R10 = 0xa 238 | R11 = 0xb 239 | R12 = 0xc 240 | R13 = 0xd 241 | R14 = 0xe 242 | R15 = 0xf 243 | */ 244 | switch(type) { 245 | case 0: 246 | switch(code) { 247 | case 0x10: 248 | reg = X86_REG_AL; 249 | break; 250 | case 0x20: 251 | reg = X86_REG_AH; 252 | break; 253 | case 0x30: 254 | reg = X86_REG_AX; 255 | break; 256 | case 0x40: 257 | reg = X86_REG_EAX; 258 | break; 259 | case 0x50: 260 | reg = X86_REG_RAX; 261 | break; 262 | } 263 | break; 264 | case 1: 265 | switch(code) { 266 | case 0x10: 267 | reg = X86_REG_BL; 268 | break; 269 | case 0x20: 270 | reg = X86_REG_BH; 271 | break; 272 | case 0x30: 273 | reg = X86_REG_BX; 274 | break; 275 | case 0x40: 276 | reg = X86_REG_EBX; 277 | break; 278 | case 0x50: 279 | reg = X86_REG_RBX; 280 | break; 281 | } 282 | break; 283 | case 2: 284 | switch(code) { 285 | case 0x10: 286 | reg = X86_REG_CL; 287 | break; 288 | case 0x20: 289 | reg = X86_REG_CH; 290 | break; 291 | case 0x30: 292 | reg = X86_REG_CX; 293 | break; 294 | case 0x40: 295 | reg = X86_REG_ECX; 296 | break; 297 | case 0x50: 298 | reg = X86_REG_RCX; 299 | break; 300 | } 301 | break; 302 | case 3: 303 | switch(code) { 304 | case 0x10: 305 | reg = X86_REG_DL; 306 | break; 307 | case 0x20: 308 | reg = X86_REG_DH; 309 | break; 310 | case 0x30: 311 | reg = X86_REG_DX; 312 | break; 313 | case 0x40: 314 | reg = X86_REG_EDX; 315 | break; 316 | case 0x50: 317 | reg = X86_REG_RDX; 318 | break; 319 | } 320 | break; 321 | case 4: 322 | switch(code) { 323 | case 0x10: 324 | reg = X86_REG_SPL; 325 | break; 326 | case 0x20: 327 | reg = X86_REG_INVALID; 328 | break; 329 | case 0x30: 330 | reg = X86_REG_SP; 331 | break; 332 | case 0x40: 333 | reg = X86_REG_ESP; 334 | break; 335 | case 0x50: 336 | reg = X86_REG_RSP; 337 | break; 338 | } 339 | break; 340 | case 5: 341 | switch(code) { 342 | case 0x10: 343 | reg = X86_REG_BPL; 344 | break; 345 | case 0x20: 346 | reg = X86_REG_INVALID; 347 | break; 348 | case 0x30: 349 | reg = X86_REG_BP; 350 | break; 351 | case 0x40: 352 | reg = X86_REG_EBP; 353 | break; 354 | case 0x50: 355 | reg = X86_REG_RBP; 356 | break; 357 | } 358 | break; 359 | case 6: 360 | switch(code) { 361 | case 0x10: 362 | reg = X86_REG_SIL; 363 | break; 364 | case 0x20: 365 | reg = X86_REG_INVALID; 366 | break; 367 | case 0x30: 368 | reg = X86_REG_SI; 369 | break; 370 | case 0x40: 371 | reg = X86_REG_ESI; 372 | break; 373 | case 0x50: 374 | reg = X86_REG_RSI; 375 | break; 376 | } 377 | break; 378 | case 7: 379 | switch(code) { 380 | case 0x10: 381 | reg = X86_REG_DIL; 382 | break; 383 | case 0x20: 384 | reg = X86_REG_INVALID; 385 | break; 386 | case 0x30: 387 | reg = X86_REG_DI; 388 | break; 389 | case 0x40: 390 | reg = X86_REG_EDI; 391 | break; 392 | case 0x50: 393 | reg = X86_REG_RDI; 394 | break; 395 | } 396 | break; 397 | case 8: 398 | switch(code) { 399 | case 0x10: 400 | reg = X86_REG_R8B; 401 | break; 402 | case 0x20: 403 | reg = X86_REG_INVALID; 404 | break; 405 | case 0x30: 406 | reg = X86_REG_R8W; 407 | break; 408 | case 0x40: 409 | reg = X86_REG_R8D; 410 | break; 411 | case 0x50: 412 | reg = X86_REG_R8; 413 | break; 414 | } 415 | break; 416 | case 9: 417 | switch(code) { 418 | case 0x10: 419 | reg = X86_REG_R9B; 420 | break; 421 | case 0x20: 422 | reg = X86_REG_INVALID; 423 | break; 424 | case 0x30: 425 | reg = X86_REG_R9W; 426 | break; 427 | case 0x40: 428 | reg = X86_REG_R9D; 429 | break; 430 | case 0x50: 431 | reg = X86_REG_R9; 432 | break; 433 | } 434 | break; 435 | case 0xa: 436 | switch(code) { 437 | case 0x10: 438 | reg = X86_REG_R10B; 439 | break; 440 | case 0x20: 441 | reg = X86_REG_INVALID; 442 | break; 443 | case 0x30: 444 | reg = X86_REG_R10W; 445 | break; 446 | case 0x40: 447 | reg = X86_REG_R10D; 448 | break; 449 | case 0x50: 450 | reg = X86_REG_R10; 451 | break; 452 | } 453 | break; 454 | case 0xb: 455 | switch(code) { 456 | case 0x10: 457 | reg = X86_REG_R11B; 458 | break; 459 | case 0x20: 460 | reg = X86_REG_INVALID; 461 | break; 462 | case 0x30: 463 | reg = X86_REG_R11W; 464 | break; 465 | case 0x40: 466 | reg = X86_REG_R11D; 467 | break; 468 | case 0x50: 469 | reg = X86_REG_R11; 470 | break; 471 | } 472 | break; 473 | case 0xc: 474 | switch(code) { 475 | case 0x10: 476 | reg = X86_REG_R12B; 477 | break; 478 | case 0x20: 479 | reg = X86_REG_INVALID; 480 | break; 481 | case 0x30: 482 | reg = X86_REG_R12W; 483 | break; 484 | case 0x40: 485 | reg = X86_REG_R12D; 486 | break; 487 | case 0x50: 488 | reg = X86_REG_R12; 489 | break; 490 | } 491 | break; 492 | case 0xd: 493 | switch(code) { 494 | case 0x10: 495 | reg = X86_REG_R13B; 496 | break; 497 | case 0x20: 498 | reg = X86_REG_INVALID; 499 | break; 500 | case 0x30: 501 | reg = X86_REG_R13W; 502 | break; 503 | case 0x40: 504 | reg = X86_REG_R13D; 505 | break; 506 | case 0x50: 507 | reg = X86_REG_R13; 508 | break; 509 | } 510 | break; 511 | case 0xe: 512 | switch(code) { 513 | case 0x10: 514 | reg = X86_REG_R14B; 515 | break; 516 | case 0x20: 517 | reg = X86_REG_INVALID; 518 | break; 519 | case 0x30: 520 | reg = X86_REG_R14W; 521 | break; 522 | case 0x40: 523 | reg = X86_REG_R14D; 524 | break; 525 | case 0x50: 526 | reg = X86_REG_R14; 527 | break; 528 | } 529 | break; 530 | case 0xf: 531 | switch(code) { 532 | case 0x10: 533 | reg = X86_REG_R15B; 534 | break; 535 | case 0x20: 536 | reg = X86_REG_INVALID; 537 | break; 538 | case 0x30: 539 | reg = X86_REG_R15W; 540 | break; 541 | case 0x40: 542 | reg = X86_REG_R15D; 543 | break; 544 | case 0x50: 545 | reg = X86_REG_R15; 546 | break; 547 | } 548 | break; 549 | } 550 | return reg; 551 | } 552 | 553 | bool is_same_register_type(uint8_t reg1, uint8_t reg2) { 554 | return ((register_type(reg1) & 0xF) == (register_type(reg2) & 0xF)); 555 | } 556 | 557 | bool is_segment_reg(uint8_t reg) { 558 | switch(reg) { 559 | case X86_REG_CS: 560 | case X86_REG_SS: 561 | case X86_REG_DS: 562 | case X86_REG_ES: 563 | case X86_REG_FS: 564 | case X86_REG_GS: 565 | return true; 566 | } 567 | return false; 568 | } 569 | 570 | uint64_t resize_immediate(uint64_t imm, uint8_t reg) { 571 | uint8_t reg_code = register_type(reg) & 0xF0; 572 | switch(reg_code) { 573 | case 0x10: 574 | imm &= 0xFF; 575 | break; 576 | case 0x30: 577 | imm &= 0xFFFF; 578 | break; 579 | case 0x40: 580 | imm &= 0xFFFFFFFF; 581 | break; 582 | } 583 | return imm; 584 | } 585 | 586 | bool is_valid(uint8_t reg) { 587 | return (reg != X86_REG_INVALID); 588 | } -------------------------------------------------------------------------------- /Rewrite/deob/optimizations_old.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 5 | Name: expand_stack_ins 6 | Description: this function is used to expand 7 | a list of instruction to facilitate the analysis 8 | & possible optimization of the stack or memory. 9 | Current expansion list: 10 | 11 | -------------PUSH------------- 12 | 0 = PUSH IMM 13 | 1 = PUSH REG 14 | 2 = PUSH SEG 15 | 3 = PUSH [BASE+INDEX*SCALE+DISP] 16 | 4 = PUSHF 17 | -- 5 = PUSHFD 18 | -- 6 = PUSHFQ 19 | -- 7 = PUSHAW (Intel Manual: PUSHA) 20 | 8 = PUSHAL (Intel Manual: PUSHAD) 21 | -------------POP-------------- 22 | 9 = POP REG 23 | 10 = POP SEG 24 | 11 = POP [BASE+INDEX*SCALE+DISP] 25 | 12 = POPF 26 | -- 13 = POPFD 27 | -- 14 = POPFQ 28 | -- 15 = POPAW (Intel Manual: POPA) 29 | 16 = POPAL (Intel Manual: POPAD) 30 | -------------MOV-------------- 31 | 17 = MOV REG, ESP/RSP 32 | 18 = MOV[BASE+INDEX*SCALE+DISP], ESP/RSP 33 | -------------XCHG------------- 34 | 19 = XCHG [BASE+INDEX*SCALE+DISP], REG 35 | 20 = XCHG REG1, REG2 36 | -------------LEA-------------- 37 | 21 = LEA REG, [BASE+INDEX*SCALE+DISP] 38 | ------------------------------ 39 | 0xFF = Do not expand 40 | */ 41 | 42 | bool expand_stack_ins(csh handle, List *list, uint8_t mode) { 43 | bool optimized = false; 44 | //check if list contains at least an instruction 45 | if(!list->first) return false; 46 | //start the expansion from the first instruction 47 | ListEntry *current = list->first, *next; 48 | //setup Capstone variables 49 | cs_insn *insn; 50 | cs_x86 *x86; 51 | cs_x86_op *op; 52 | size_t op_count; 53 | //ID is the instruction expansion identifier 54 | uint8_t ID; 55 | Instruction *current_insn; 56 | while(current) { 57 | //printf("current: %s %s\n", current->insn->mnemonic, current->insn->op_str); 58 | next = current->next; 59 | //reset instruction ID = 0xFF = Do not expand 60 | ID = 0xFF; 61 | //identify instruction (using mnemonic & operands) 62 | current_insn = (Instruction *)current->content; 63 | insn = current_insn->insn; 64 | if(strncmp(insn->mnemonic, "push", 4) == 0) { 65 | if(strncmp(insn->mnemonic, "pushf", 5) == 0) { 66 | ID = 4; 67 | } else if(strncmp(insn->mnemonic, "pushal", 6) == 0) { 68 | ID = 8; 69 | } 70 | //If the instruction is none of the above check for 1/2/3 71 | x86 = &(insn->detail->x86); 72 | op_count = x86->op_count; 73 | for(size_t i = 0; i < op_count; i++) { 74 | op = &(x86->operands[i]); 75 | switch(op->type) { 76 | case X86_OP_REG: 77 | ID = (is_segment_reg(op->reg)) ? 2 : 1; 78 | break; 79 | case X86_OP_MEM: 80 | ID = 3; 81 | break; 82 | case X86_OP_IMM: 83 | ID = 0; 84 | break; 85 | } 86 | } 87 | } else if(strncmp(insn->mnemonic, "pop", 3) == 0) { 88 | if(strncmp(insn->mnemonic, "popf", 4) == 0) { 89 | ID = 12; 90 | } else if(strncmp(insn->mnemonic, "popal", 5) == 0) { 91 | ID = 16; 92 | } 93 | //If the instruction is none of the above check for 9/10/11 94 | x86 = &(insn->detail->x86); 95 | op_count = x86->op_count; 96 | for(size_t i = 0; i < op_count; i++) { 97 | op = &(x86->operands[i]); 98 | switch(op->type) { 99 | case X86_OP_REG: 100 | ID = (is_segment_reg(op->reg)) ? 10 : 9; 101 | break; 102 | case X86_OP_MEM: 103 | ID = 11; 104 | break; 105 | } 106 | } 107 | } else if(strncmp(insn->mnemonic, "mov", 3) == 0) { 108 | //check if it is "MOV REG, ESP" 109 | x86 = &(insn->detail->x86); 110 | op_count = x86->op_count; 111 | bool dest_reg_found = false, src_reg_found = false, mem_write_found = false, src_esp_found = false; 112 | for(size_t i = 0; i < op_count; i++) { 113 | op = &(x86->operands[i]); 114 | if(op->access == CS_AC_WRITE && op->type == X86_OP_REG) dest_reg_found = true; 115 | if(op->access == CS_AC_READ && op->type == X86_OP_REG && op->reg != X86_REG_INVALID && is_same_register_type(op->reg, X86_REG_RSP)) src_reg_found = true; 116 | if(op->type == X86_OP_MEM && ((op->mem.base == X86_REG_ESP) || (op->mem.base == X86_REG_RSP))) mem_write_found = true; 117 | if(op->access == CS_AC_READ && op->type == X86_OP_REG && is_same_register_type(op->reg, X86_REG_RSP)) src_esp_found = true; 118 | } 119 | if(dest_reg_found && src_reg_found) ID = 17; 120 | if(src_esp_found && mem_write_found) ID = 18; 121 | } else if(strncmp(insn->mnemonic, "xchg", 4) == 0) { 122 | //check if it is "XCHG [MEM], REG" 123 | x86 = &(insn->detail->x86); 124 | op_count = x86->op_count; 125 | for(size_t i = 0; i < op_count; i++) { 126 | op = &(x86->operands[i]); 127 | if(op->type == X86_OP_MEM) ID = 19; 128 | } 129 | //if ID == 0xFF this is not "XCHG [MEM], REG", it is "XCHG REG1, REG2" 130 | if(ID == 0xFF) ID = 20; 131 | } else if(strncmp(insn->mnemonic, "lea", 3) == 0) { 132 | //this is a general lea instruction 133 | ID = 21; 134 | } 135 | //apply expansion based on the ID 136 | switch(ID) { 137 | //0 = PUSH IMM 138 | case 0: { 139 | //generating mnemonic & op_str 140 | cs_insn *mov = calloc(1, sizeof(cs_insn)); 141 | cs_insn *sub = calloc(1, sizeof(cs_insn)); 142 | sprintf(mov->mnemonic, "mov"); 143 | sprintf(sub->mnemonic, "sub"); 144 | //uint8_t displacement = (mode == CS_MODE_32) ? 4 : 8; 145 | uint8_t op_size; 146 | get_op_size(current_insn, REG_FIRST, &op_size); 147 | char *mem_size = calloc(10, sizeof(char)); 148 | switch(op_size) { 149 | case 1: 150 | sprintf(mem_size, "byte"); 151 | break; 152 | case 2: 153 | sprintf(mem_size, "word"); 154 | break; 155 | case 4: 156 | sprintf(mem_size, "dword"); 157 | break; 158 | case 8: 159 | sprintf(mem_size, "qword"); 160 | break; 161 | } 162 | uint8_t esp_reg = (mode == CS_MODE_32) ? X86_REG_ESP : X86_REG_RSP; 163 | sprintf(mov->op_str, "%s ptr [%s - %d], %s", mem_size, cs_reg_name(handle, esp_reg), op_size, insn->op_str); 164 | sprintf(sub->op_str, "%s, %d", cs_reg_name(handle, esp_reg), op_size); 165 | //assembling new Instructions 166 | Instruction *mov_ins = assemble_insn(mov->mnemonic, mov->op_str, TEXT_ADDRESS, mode); 167 | Instruction *sub_ins = assemble_insn(sub->mnemonic, sub->op_str, TEXT_ADDRESS, mode); 168 | if(!mov_ins || !sub_ins) { 169 | if(VERBOSE_ERROR) printf("[-] Error: reassemble() || update_disasm() - expand_stack_ins\n"); 170 | return false; 171 | } else { 172 | //printf("\noriginal: %s %s\n", insn->mnemonic, insn->op_str); 173 | //printf("%s %s\n", mov_ins->insn->mnemonic, mov_ins->insn->op_str); 174 | //printf("%s %s\n", sub_ins->insn->mnemonic, sub_ins->insn->op_str); 175 | ListEntry *mov_entry = ListEntryCreate(mov_ins); 176 | ListEntry *sub_entry = ListEntryCreate(sub_ins); 177 | //add instructions to the list 178 | ListInsertAfter(list, current, mov_entry); 179 | ListInsertAfter(list, mov_entry, sub_entry); 180 | ListRemove(list, current); 181 | free(mov); 182 | free(sub); 183 | optimized = true; 184 | break; 185 | } 186 | } 187 | //1 = PUSH REG 188 | case 1: { 189 | //generating mnemonic & op_str 190 | cs_insn *mov = calloc(1, sizeof(cs_insn)); 191 | cs_insn *sub = calloc(1, sizeof(cs_insn)); 192 | sprintf(mov->mnemonic, "mov"); 193 | sprintf(sub->mnemonic, "sub"); 194 | //find out if the pushed register is 16/32/64 bit 195 | uint8_t op_size = 0; 196 | x86 = &(insn->detail->x86); 197 | op_count = x86->op_count; 198 | for(size_t i = 0; i < op_count; i++) { 199 | op = &(x86->operands[i]); 200 | if(op->type == X86_OP_REG) { 201 | switch(register_type(op->reg) & 0xF0) { 202 | case 0x30: 203 | op_size = 16; 204 | break; 205 | case 0x40: 206 | op_size = 32; 207 | break; 208 | case 0x50: 209 | op_size = 64; 210 | break; 211 | } 212 | } 213 | } 214 | if(op_size == 0) { 215 | printf("[!] Error retrieving pushed register size in bits\n"); 216 | return false; 217 | } 218 | //generating correct instructions 219 | switch(mode) { 220 | case CS_MODE_32: 221 | switch(op_size) { 222 | case 16: 223 | sprintf(mov->op_str, "[esp-2], %s", insn->op_str); 224 | sprintf(sub->op_str, "esp, 2"); 225 | break; 226 | case 32: 227 | sprintf(mov->op_str, "[esp-4], %s", insn->op_str); 228 | sprintf(sub->op_str, "esp, 4"); 229 | break; 230 | } 231 | break; 232 | case CS_MODE_64: 233 | switch(op_size) { 234 | case 16: 235 | sprintf(mov->op_str, "[rsp-2], %s", insn->op_str); 236 | sprintf(sub->op_str, "rsp, 2"); 237 | break; 238 | case 32: 239 | sprintf(mov->op_str, "[rsp-4], %s", insn->op_str); 240 | sprintf(sub->op_str, "rsp, 4"); 241 | break; 242 | case 64: 243 | sprintf(mov->op_str, "[rsp-8], %s", insn->op_str); 244 | sprintf(sub->op_str, "rsp, 8"); 245 | break; 246 | } 247 | break; 248 | } 249 | //assembling new Instructions 250 | Instruction *mov_ins = assemble_insn(mov->mnemonic, mov->op_str, TEXT_ADDRESS, mode); 251 | Instruction *sub_ins = assemble_insn(sub->mnemonic, sub->op_str, TEXT_ADDRESS, mode); 252 | if(!mov_ins || !sub_ins) { 253 | if(VERBOSE_ERROR) printf("[-] Error: reassemble() || update_disasm() - expand_stack_ins\n"); 254 | return false; 255 | } else { 256 | //printf("\noriginal: %s %s\n", insn->mnemonic, insn->op_str); 257 | //printf("%s %s\n", mov_ins->insn->mnemonic, mov_ins->insn->op_str); 258 | //printf("%s %s\n", sub_ins->insn->mnemonic, sub_ins->insn->op_str); 259 | ListEntry *mov_entry = ListEntryCreate(mov_ins); 260 | ListEntry *sub_entry = ListEntryCreate(sub_ins); 261 | //add instructions to the list 262 | ListInsertAfter(list, current, mov_entry); 263 | ListInsertAfter(list, mov_entry, sub_entry); 264 | ListRemove(list, current); 265 | free(mov); 266 | free(sub); 267 | optimized = true; 268 | } 269 | break; 270 | } 271 | //2 = PUSH SEG 272 | case 2: { 273 | // This instruction cannot be converted into a pair "MOV/SUB", I will handle it in this way: 274 | // 1) I will create a fake instruction "MOV [MEM], SEG" + "SUB ESP/RSP, 4/8" 275 | // 2) I will mark the instruction as INVALID, so other optimization methods can ignore it if needed 276 | //retrieve real SEGMENT register 277 | uint8_t seg_reg = X86_REG_INVALID; 278 | x86 = &(insn->detail->x86); 279 | op_count = x86->op_count; 280 | for(size_t i = 0; i < op_count; i++) { 281 | op = &(x86->operands[i]); 282 | if(op->type == X86_OP_REG) { 283 | seg_reg = op->reg; 284 | } 285 | } 286 | //generating mnemonic & op_str 287 | cs_insn *mov = calloc(1, sizeof(cs_insn)); 288 | cs_insn *sub = calloc(1, sizeof(cs_insn)); 289 | sprintf(mov->mnemonic, "mov"); 290 | sprintf(sub->mnemonic, "sub"); 291 | char *fake_op_str = calloc(40, sizeof(char)); 292 | uint8_t displacement = (mode == CS_MODE_32) ? 4 : 8; 293 | uint8_t src_reg = (mode == CS_MODE_32) ? X86_REG_EAX : X86_REG_RAX; 294 | uint8_t esp_reg = (mode == CS_MODE_32) ? X86_REG_ESP : X86_REG_RSP; 295 | sprintf(mov->op_str, "[%s-%d], %s", cs_reg_name(handle, esp_reg), displacement, cs_reg_name(handle, src_reg)); 296 | sprintf(mov->op_str, "[%s-%d], %s", cs_reg_name(handle, esp_reg), displacement, cs_reg_name(handle, seg_reg)); 297 | sprintf(sub->op_str, "%s, %d", cs_reg_name(handle, esp_reg), displacement); 298 | //generating new Instructions 299 | Instruction *mov_ins = assemble_fake_insn(mov->mnemonic, mov->op_str, fake_op_str, TEXT_ADDRESS, mode); 300 | Instruction *sub_ins = assemble_insn(sub->mnemonic, sub->op_str, TEXT_ADDRESS, mode); 301 | if(!mov_ins || !sub_ins) { 302 | if(VERBOSE_ERROR) printf("[-] Error: reassemble() || update_disasm() - expand_stack_ins\n"); 303 | return false; 304 | } else { 305 | //fixing fake operands 306 | mov_ins->insn->detail->x86.operands[1].reg = seg_reg; 307 | //create ListEntry 308 | //printf("\noriginal: %s %s\n", insn->mnemonic, insn->op_str); 309 | //printf("%s %s\n", mov_ins->insn->mnemonic, mov_ins->insn->op_str); 310 | //printf("%s %s\n", sub_ins->insn->mnemonic, sub_ins->insn->op_str); 311 | ListEntry *mov_entry = ListEntryCreate(mov_ins); 312 | ListEntry *sub_entry = ListEntryCreate(sub_ins); 313 | //add instructions to the list 314 | ListInsertAfter(list, current, mov_entry); 315 | ListInsertAfter(list, mov_entry, sub_entry); 316 | ListRemove(list, current); 317 | free(fake_op_str); 318 | free(mov); 319 | free(sub); 320 | optimized = true; 321 | } 322 | break; 323 | } 324 | //3 = PUSH [BASE+INDEX*SCALE+DISP] 325 | case 3: { 326 | //extract base, index, scale & displacement from the current instruction 327 | uint32_t disp = 0, scale = 1; 328 | uint8_t base = X86_REG_INVALID, index = X86_REG_INVALID, mem_size = 0; 329 | x86 = &(current_insn->insn->detail->x86); 330 | op_count = x86->op_count; 331 | for(size_t i = 0; i < op_count; i++) { 332 | op = &(x86->operands[i]); 333 | if(op->type == X86_OP_MEM) { 334 | base =op->mem.base; 335 | index = op->mem.index; 336 | scale = (uint32_t)op->mem.scale; 337 | disp = (uint32_t)op->mem.disp; 338 | mem_size = op->size; 339 | } 340 | } 341 | //generating mnemonic & op_str 342 | cs_insn *mov1 = calloc(1, sizeof(cs_insn)); 343 | cs_insn *mov2 = calloc(1, sizeof(cs_insn)); 344 | cs_insn *mov3 = calloc(1, sizeof(cs_insn)); 345 | cs_insn *mov4 = calloc(1, sizeof(cs_insn)); 346 | cs_insn *sub = calloc(1, sizeof(cs_insn)); 347 | sprintf(mov1->mnemonic, "mov"); 348 | sprintf(mov2->mnemonic, "mov"); 349 | sprintf(mov3->mnemonic, "mov"); 350 | sprintf(mov4->mnemonic, "mov"); 351 | sprintf(sub->mnemonic, "sub"); 352 | //generate memory size indicator 353 | char *mem_size_indicator = calloc(20, sizeof(char)); 354 | switch(mem_size) { 355 | case 1: 356 | sprintf(mem_size_indicator, "byte"); 357 | break; 358 | case 2: 359 | sprintf(mem_size_indicator, "word"); 360 | break; 361 | case 4: 362 | sprintf(mem_size_indicator, "dword"); 363 | break; 364 | case 8: 365 | sprintf(mem_size_indicator, "qword"); 366 | break; 367 | } 368 | //generate instructions op_str 369 | uint8_t src_reg = (mode == CS_MODE_32) ? X86_REG_EAX : X86_REG_RAX; 370 | uint8_t esp_reg = (mode == CS_MODE_32) ? X86_REG_ESP : X86_REG_RSP; 371 | uint8_t displacement = (mode == CS_MODE_32) ? 4 : 8; 372 | sprintf(mov1->op_str, "[%s - 0x%lx], %s", cs_reg_name(handle, esp_reg), STACK_DISPLACEMENT, cs_reg_name(handle, src_reg)); 373 | sprintf(mov2->op_str, "%s, [%s + %s * 0x%lx + 0x%lx]", cs_reg_name(handle, src_reg), cs_reg_name(handle, base), cs_reg_name(handle, index), scale, disp); 374 | sprintf(mov3->op_str, "%s [%s - %d], %s", mem_size_indicator, cs_reg_name(handle, esp_reg), displacement, cs_reg_name(handle, src_reg)); 375 | sprintf(sub->op_str, "%s, %d", cs_reg_name(handle, esp_reg), mem_size); 376 | sprintf(mov4->op_str, "%s, [%s - 0x%lx]", cs_reg_name(handle, src_reg), cs_reg_name(handle, esp_reg), STACK_DISPLACEMENT); 377 | //printf("%s, %s\n", mov1->mnemonic, mov1->op_str); 378 | //printf("%s, %s\n", mov2->mnemonic, mov2->op_str); 379 | //printf("%s, %s\n", mov3->mnemonic, mov3->op_str); 380 | //printf("%s, %s\n", mov4->mnemonic, mov4->op_str); 381 | //printf("%s, %s\n", sub->mnemonic, sub->op_str); 382 | //generating new Instructions 383 | Instruction *mov1_ins = assemble_insn(mov1->mnemonic, mov1->op_str, TEXT_ADDRESS, mode); 384 | Instruction *mov2_ins = assemble_insn(mov2->mnemonic, mov2->op_str, TEXT_ADDRESS, mode); 385 | Instruction *mov3_ins = assemble_insn(mov3->mnemonic, mov3->op_str, TEXT_ADDRESS, mode); 386 | Instruction *mov4_ins = assemble_insn(mov4->mnemonic, mov4->op_str, TEXT_ADDRESS, mode); 387 | Instruction *sub_ins = assemble_insn(sub->mnemonic, sub->op_str, TEXT_ADDRESS, mode); 388 | //assemble instructions 389 | if(!mov1_ins || !mov2_ins || !mov3_ins || !mov4_ins || !sub_ins) { 390 | if(VERBOSE_ERROR) printf("[-] Error: reassemble() || update_disasm() - expand_stack_ins\n"); 391 | return false; 392 | } else { 393 | ListEntry *mov1_entry = ListEntryCreate(mov1_ins); 394 | ListEntry *mov2_entry = ListEntryCreate(mov2_ins); 395 | ListEntry *mov3_entry = ListEntryCreate(mov3_ins); 396 | ListEntry *mov4_entry = ListEntryCreate(mov4_ins); 397 | ListEntry *sub_entry = ListEntryCreate(sub_ins); 398 | //add instructions to the list 399 | ListInsertAfter(list, current, mov1_entry); 400 | ListInsertAfter(list, mov1_entry, mov2_entry); 401 | ListInsertAfter(list, mov2_entry, mov3_entry); 402 | ListInsertAfter(list, mov3_entry, mov4_entry); 403 | ListInsertAfter(list, mov4_entry, sub_entry); 404 | ListRemove(list, current); 405 | free(mem_size_indicator); 406 | free(mov1); 407 | free(mov2); 408 | free(mov3); 409 | free(mov4); 410 | free(sub); 411 | optimized = true; 412 | } 413 | break; 414 | } 415 | //4 = PUSHF 416 | case 4: { 417 | // This instruction cannot be converted into a pair "MOV/SUB", I will handle it in this way: 418 | // 1) I will create a fake instruction "MOV [MEM], EFLAGS" + "SUB ESP/RSP, 4/8" 419 | // 2) I will mark the instruction as INVALID, so other optimization methods can ignore it if needed 420 | //generating mnemonic & op_str 421 | cs_insn *mov = calloc(1, sizeof(cs_insn)); 422 | cs_insn *sub = calloc(1, sizeof(cs_insn)); 423 | sprintf(mov->mnemonic, "mov"); 424 | sprintf(sub->mnemonic, "sub"); 425 | uint8_t displacement = (mode == CS_MODE_32) ? 4 : 8; 426 | uint8_t esp_reg = (mode == CS_MODE_32) ? X86_REG_ESP : X86_REG_RSP; 427 | uint8_t src_reg = (mode == CS_MODE_32) ? X86_REG_EAX : X86_REG_RAX; 428 | sprintf(mov->op_str, "[%s - %d], %s", cs_reg_name(handle, esp_reg), displacement, cs_reg_name(handle, src_reg)); 429 | sprintf(sub->op_str, "esp, 4"); 430 | char *fake_op_str = calloc(40, sizeof(char)); 431 | sprintf(fake_op_str, "[%s - %d], %s", cs_reg_name(handle, esp_reg), displacement, cs_reg_name(handle, X86_REG_EFLAGS)); 432 | //generating new Instructions 433 | Instruction *mov_ins = assemble_fake_insn(mov->mnemonic, mov->op_str, fake_op_str, TEXT_ADDRESS, mode); 434 | Instruction *sub_ins = assemble_insn(sub->mnemonic, sub->op_str, TEXT_ADDRESS, mode); 435 | if(!mov_ins || !sub_ins) { 436 | if(VERBOSE_ERROR) printf("[-] Error: reassemble() || update_disasm() - expand_stack_ins\n"); 437 | return false; 438 | } else { 439 | //fixing fake operands 440 | mov_ins->insn->detail->x86.operands[1].reg = X86_REG_EFLAGS; 441 | //create ListEntry 442 | ListEntry *mov_entry = ListEntryCreate(mov_ins); 443 | ListEntry *sub_entry = ListEntryCreate(sub_ins); 444 | //add instructions to the list 445 | ListInsertAfter(list, current, mov_entry); 446 | ListInsertAfter(list, mov_entry, sub_entry); 447 | ListRemove(list, current); 448 | free(fake_op_str); 449 | free(mov); 450 | free(sub); 451 | optimized = true; 452 | } 453 | break; 454 | } 455 | //8 = PUSHAL 456 | case 8: { 457 | switch(mode) { 458 | case CS_MODE_32: { 459 | //I have to simulate the push of: EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI 460 | cs_insn *mov_eax = calloc(1, sizeof(cs_insn)); 461 | cs_insn *mov_ecx = calloc(1, sizeof(cs_insn)); 462 | cs_insn *mov_edx = calloc(1, sizeof(cs_insn)); 463 | cs_insn *mov_ebx = calloc(1, sizeof(cs_insn)); 464 | cs_insn *mov_esp = calloc(1, sizeof(cs_insn)); 465 | cs_insn *mov_ebp = calloc(1, sizeof(cs_insn)); 466 | cs_insn *mov_esi = calloc(1, sizeof(cs_insn)); 467 | cs_insn *mov_edi = calloc(1, sizeof(cs_insn)); 468 | cs_insn *sub = calloc(1, sizeof(cs_insn)); 469 | //generating mnemonic 470 | sprintf(mov_eax->mnemonic, "mov"); 471 | sprintf(mov_ecx->mnemonic, "mov"); 472 | sprintf(mov_edx->mnemonic, "mov"); 473 | sprintf(mov_ebx->mnemonic, "mov"); 474 | sprintf(mov_esp->mnemonic, "mov"); 475 | sprintf(mov_ebp->mnemonic, "mov"); 476 | sprintf(mov_esi->mnemonic, "mov"); 477 | sprintf(mov_edi->mnemonic, "mov"); 478 | sprintf(sub->mnemonic, "sub"); 479 | //generating op_str 480 | sprintf(mov_eax->op_str, "[esp-0x20], eax"); 481 | sprintf(mov_ecx->op_str, "[esp-0x1c], ecx"); 482 | sprintf(mov_edx->op_str, "[esp-0x18], edx"); 483 | sprintf(mov_ebx->op_str, "[esp-0x14], ebx"); 484 | sprintf(mov_esp->op_str, "[esp-0x10], esp"); 485 | sprintf(mov_ebp->op_str, "[esp-0xc], ebp"); 486 | sprintf(mov_esi->op_str, "[esp-8], esi"); 487 | sprintf(mov_edi->op_str, "[esp-4], edi"); 488 | sprintf(sub->op_str, "esp, 0x20"); 489 | //generating new Instructions 490 | Instruction *mov_eax_ins = assemble_insn(mov_eax->mnemonic, mov_eax->op_str, TEXT_ADDRESS, mode); 491 | Instruction *mov_ecx_ins = assemble_insn(mov_ecx->mnemonic, mov_ecx->op_str, TEXT_ADDRESS, mode); 492 | Instruction *mov_edx_ins = assemble_insn(mov_edx->mnemonic, mov_edx->op_str, TEXT_ADDRESS, mode); 493 | Instruction *mov_ebx_ins = assemble_insn(mov_ebx->mnemonic, mov_ebx->op_str, TEXT_ADDRESS, mode); 494 | Instruction *mov_esp_ins = assemble_insn(mov_esp->mnemonic, mov_esp->op_str, TEXT_ADDRESS, mode); 495 | Instruction *mov_ebp_ins = assemble_insn(mov_ebp->mnemonic, mov_ebp->op_str, TEXT_ADDRESS, mode); 496 | Instruction *mov_esi_ins = assemble_insn(mov_esi->mnemonic, mov_esi->op_str, TEXT_ADDRESS, mode); 497 | Instruction *mov_edi_ins = assemble_insn(mov_edi->mnemonic, mov_edi->op_str, TEXT_ADDRESS, mode); 498 | Instruction *sub_ins = assemble_insn(sub->mnemonic, sub->op_str, TEXT_ADDRESS, mode); 499 | //printf("\n[%s %s]\n", mov_eax->mnemonic, mov_eax->op_str); 500 | //printf("[%s %s]\n", mov_ecx->mnemonic, mov_ecx->op_str); 501 | //printf("[%s %s]\n", mov_edx->mnemonic, mov_edx->op_str); 502 | //printf("[%s %s]\n", mov_ebx->mnemonic, mov_ebx->op_str); 503 | //printf("[%s %s]\n", mov_esp->mnemonic, mov_esp->op_str); 504 | //printf("[%s %s]\n", mov_ebp->mnemonic, mov_ebp->op_str); 505 | //printf("[%s %s]\n", mov_esi->mnemonic, mov_esi->op_str); 506 | //printf("[%s %s]\n", mov_edi->mnemonic, mov_edi->op_str); 507 | //printf("[%s %s]\n\n", sub->mnemonic, sub->op_str); 508 | //assemble instructions 509 | if(!mov_eax_ins || !mov_ebx_ins || !mov_ecx_ins || !mov_edx_ins || !mov_esp_ins || !mov_ebp_ins || !mov_esi_ins || !mov_edi_ins) { 510 | if(VERBOSE_ERROR) printf("[-] Error: reassemble() || update_disasm() - expand_stack_ins\n"); 511 | return false; 512 | } else { 513 | ListEntry *mov_eax_entry = ListEntryCreate(mov_eax_ins); 514 | ListEntry *mov_ecx_entry = ListEntryCreate(mov_ecx_ins); 515 | ListEntry *mov_edx_entry = ListEntryCreate(mov_edx_ins); 516 | ListEntry *mov_ebx_entry = ListEntryCreate(mov_ebx_ins); 517 | ListEntry *mov_esp_entry = ListEntryCreate(mov_esp_ins); 518 | ListEntry *mov_ebp_entry = ListEntryCreate(mov_ebp_ins); 519 | ListEntry *mov_esi_entry = ListEntryCreate(mov_esi_ins); 520 | ListEntry *mov_edi_entry = ListEntryCreate(mov_edi_ins); 521 | ListEntry *sub_entry = ListEntryCreate(sub_ins); 522 | //add instructions to the list 523 | ListInsertAfter(list, current, mov_eax_entry); 524 | ListInsertAfter(list, mov_eax_entry, mov_ecx_entry); 525 | ListInsertAfter(list, mov_ecx_entry, mov_edx_entry); 526 | ListInsertAfter(list, mov_edx_entry, mov_ebx_entry); 527 | ListInsertAfter(list, mov_ebx_entry, mov_esp_entry); 528 | ListInsertAfter(list, mov_esp_entry, mov_ebp_entry); 529 | ListInsertAfter(list, mov_ebp_entry, mov_esi_entry); 530 | ListInsertAfter(list, mov_esi_entry, mov_edi_entry); 531 | ListInsertAfter(list, mov_edi_entry, sub_entry); 532 | ListRemove(list, current); 533 | free(mov_eax); 534 | free(mov_ecx); 535 | free(mov_edx); 536 | free(mov_ebx); 537 | free(mov_esp); 538 | free(mov_ebp); 539 | free(mov_esi); 540 | free(mov_edi); 541 | free(sub); 542 | optimized = true; 543 | } 544 | break; 545 | } 546 | case CS_MODE_64: 547 | //the instruction does not exist 548 | break; 549 | } 550 | break; 551 | } 552 | //9 = POP REG 553 | case 9: { 554 | //retrieving destination size 555 | uint8_t op_size = 0; 556 | x86 = &(insn->detail->x86); 557 | op_count = x86->op_count; 558 | for(size_t i = 0; i < op_count; i++) { 559 | op = &(x86->operands[i]); 560 | if(op->type == X86_OP_REG) { 561 | op_size = op->size; 562 | } 563 | } 564 | //generating mnemonic & op_str 565 | cs_insn *mov = calloc(1, sizeof(cs_insn)); 566 | cs_insn *add = calloc(1, sizeof(cs_insn)); 567 | sprintf(mov->mnemonic, "mov"); 568 | sprintf(add->mnemonic, "add"); 569 | uint8_t esp_reg = (mode == CS_MODE_32) ? X86_REG_ESP : X86_REG_RSP; 570 | sprintf(mov->op_str, "%s, [%s - %d]", insn->op_str, cs_reg_name(handle, esp_reg), op_size); 571 | sprintf(add->op_str, "%s, %d", cs_reg_name(handle, esp_reg), op_size); 572 | //generating new Instructions 573 | Instruction *mov_ins = assemble_insn(mov->mnemonic, mov->op_str, TEXT_ADDRESS, mode); 574 | Instruction *add_ins = assemble_insn(add->mnemonic, add->op_str, TEXT_ADDRESS, mode); 575 | //printf("%s %s\n", add->mnemonic, add->op_str); 576 | //printf("%s %s\n\n", mov->mnemonic, mov->op_str); 577 | //assemble instructions 578 | if(!mov_ins || !add_ins) { 579 | if(VERBOSE_ERROR) printf("[-] Error: reassemble() || update_disasm() - expand_stack_ins\n"); 580 | return false; 581 | } else { 582 | ListEntry *mov_entry = ListEntryCreate(mov_ins); 583 | ListEntry *add_entry = ListEntryCreate(add_ins); 584 | //add instructions to the list 585 | ListInsertAfter(list, current, add_entry); 586 | ListInsertAfter(list, add_entry, mov_entry); 587 | ListRemove(list, current); 588 | free(add); 589 | free(mov); 590 | optimized = true; 591 | } 592 | break; 593 | } 594 | //10 = POP SEG 595 | case 10: { 596 | // This instruction cannot be converted into a pair "MOV/SUB", I will handle it in this way: 597 | // 1) I will create a fake instruction "ADD ESP/RSP, 4/8" + "MOV SEG, [MEM]" 598 | // 2) I will mark the instruction as INVALID, so other optimization methods can ignore it if needed 599 | //retrieve real SEGMENT register 600 | uint8_t seg_reg = X86_REG_INVALID; 601 | x86 = &(insn->detail->x86); 602 | op_count = x86->op_count; 603 | for(size_t i = 0; i < op_count; i++) { 604 | op = &(x86->operands[i]); 605 | if(op->type == X86_OP_REG) { 606 | seg_reg = op->reg; 607 | } 608 | } 609 | //generating mnemonic & op_str 610 | cs_insn *mov = calloc(1, sizeof(cs_insn)); 611 | cs_insn *add = calloc(1, sizeof(cs_insn)); 612 | sprintf(mov->mnemonic, "mov"); 613 | sprintf(add->mnemonic, "add"); 614 | uint8_t esp_reg = (mode == CS_MODE_32) ? X86_REG_ESP : X86_REG_RSP; 615 | uint8_t dst_reg = (mode == CS_MODE_32) ? X86_REG_EAX : X86_REG_RAX; 616 | uint8_t displacement = (mode == CS_MODE_32) ? 4 : 8; 617 | sprintf(mov->op_str, "%s, [%s - %d]", cs_reg_name(handle, dst_reg), cs_reg_name(handle, esp_reg), displacement); 618 | sprintf(add->op_str, "%s, %d", cs_reg_name(handle, esp_reg), displacement); 619 | char *fake_op_str = calloc(1, sizeof(char)); 620 | sprintf(fake_op_str, "%s, [%s - %d]", cs_reg_name(handle, seg_reg), cs_reg_name(handle, esp_reg), displacement); 621 | //generating new Instructions 622 | Instruction *mov_ins = assemble_fake_insn(mov->mnemonic, mov->op_str, fake_op_str, TEXT_ADDRESS, mode); 623 | Instruction *add_ins = assemble_insn(add->mnemonic, add->op_str, TEXT_ADDRESS, mode); 624 | //assemble FAKE instruction 625 | if(!mov_ins || !add_ins) { 626 | if(VERBOSE_ERROR) printf("[-] Error: reassemble() || update_disasm() - expand_stack_ins\n"); 627 | return false; 628 | } else { 629 | //fix segment register 630 | mov_ins->insn->detail->x86.operands[0].reg = seg_reg; 631 | ListEntry *mov_entry = ListEntryCreate(mov_ins); 632 | ListEntry *add_entry = ListEntryCreate(add_ins); 633 | //add instructions to the list 634 | ListInsertAfter(list, current, add_entry); 635 | ListInsertAfter(list, add_entry, mov_entry); 636 | ListRemove(list, current); 637 | free(fake_op_str); 638 | free(mov); 639 | free(add); 640 | optimized = true; 641 | } 642 | break; 643 | } 644 | //11 = POP [BASE+INDEX*SCALE+DISP] 645 | case 11: { 646 | //extract displacement & index from the current instruction 647 | uint32_t disp = 0, scale = 1, op_size = 0; 648 | uint8_t index = X86_REG_INVALID, base = X86_REG_INVALID; 649 | x86 = &(current_insn->insn->detail->x86); 650 | op_count = x86->op_count; 651 | for(size_t i = 0; i < op_count; i++) { 652 | op = &(x86->operands[i]); 653 | if(op->type == X86_OP_MEM) { 654 | base = op->mem.base; 655 | index = op->mem.index; 656 | scale = (uint32_t)op->mem.scale; 657 | disp = (uint32_t)op->mem.disp; 658 | op_size = op->size; 659 | } 660 | } 661 | //generating mnemonic & op_str 662 | cs_insn *mov1 = calloc(1, sizeof(cs_insn)); 663 | cs_insn *mov2 = calloc(1, sizeof(cs_insn)); 664 | cs_insn *mov3 = calloc(1, sizeof(cs_insn)); 665 | cs_insn *mov4 = calloc(1, sizeof(cs_insn)); 666 | cs_insn *add = calloc(1, sizeof(cs_insn)); 667 | sprintf(mov1->mnemonic, "mov"); 668 | sprintf(mov2->mnemonic, "mov"); 669 | sprintf(mov3->mnemonic, "mov"); 670 | sprintf(mov4->mnemonic, "mov"); 671 | sprintf(add->mnemonic, "add"); 672 | uint8_t src_reg; 673 | char *mem_size_indicator = calloc(20, sizeof(char)); 674 | switch(op_size) { 675 | case 2: 676 | sprintf(mem_size_indicator, "word"); 677 | src_reg = X86_REG_AX; 678 | break; 679 | case 4: 680 | sprintf(mem_size_indicator, "dword"); 681 | src_reg = X86_REG_EAX; 682 | break; 683 | case 8: 684 | sprintf(mem_size_indicator, "qword"); 685 | src_reg = X86_REG_RAX; 686 | break; 687 | } 688 | uint8_t tmp_reg = (mode == CS_MODE_32) ? X86_REG_EAX : X86_REG_RAX; 689 | uint8_t esp_reg = (mode == CS_MODE_32) ? X86_REG_ESP : X86_REG_RSP; 690 | sprintf(mov1->op_str, "[%s - 0x%lx], %s", cs_reg_name(handle, esp_reg), STACK_DISPLACEMENT, cs_reg_name(handle, tmp_reg)); 691 | sprintf(add->op_str, "%s, %d", cs_reg_name(handle, esp_reg), op_size); 692 | sprintf(mov2->op_str, "%s, %s [%s - %d]", cs_reg_name(handle, src_reg), mem_size_indicator, cs_reg_name(handle, esp_reg), op_size); 693 | sprintf(mov3->op_str, "%s [%s + %s * 0x%lx + 0x%lx], %s", mem_size_indicator, cs_reg_name(handle, base), cs_reg_name(handle, index), scale, disp, cs_reg_name(handle, src_reg)); 694 | sprintf(mov4->op_str, "%s, [%s - 0x%lx]", cs_reg_name(handle, tmp_reg), cs_reg_name(handle, esp_reg), STACK_DISPLACEMENT+op_size); 695 | //generating new Instructions 696 | Instruction *mov1_ins = assemble_insn(mov1->mnemonic, mov1->op_str, TEXT_ADDRESS, mode); 697 | Instruction *mov2_ins = assemble_insn(mov2->mnemonic, mov2->op_str, TEXT_ADDRESS, mode); 698 | Instruction *mov3_ins = assemble_insn(mov3->mnemonic, mov3->op_str, TEXT_ADDRESS, mode); 699 | Instruction *mov4_ins = assemble_insn(mov4->mnemonic, mov4->op_str, TEXT_ADDRESS, mode); 700 | Instruction *add_ins = assemble_insn(add->mnemonic, add->op_str, TEXT_ADDRESS, mode); 701 | //printf("original: %s %s\n", insn->mnemonic, insn->op_str); 702 | //printf("%s %s\n", mov1->mnemonic, mov1->op_str); 703 | //printf("%s %s\n", add->mnemonic, add->op_str); 704 | //printf("%s %s\n", mov2->mnemonic, mov2->op_str); 705 | //printf("%s %s\n", mov3->mnemonic, mov3->op_str); 706 | //printf("%s %s\n\n", mov4->mnemonic, mov4->op_str); 707 | //assemble instructions 708 | if(!mov1_ins || !mov2_ins || !mov3_ins || !mov4_ins || !add_ins) { 709 | if(VERBOSE_ERROR) printf("[-] Error: reassemble() || update_disasm() - expand_stack_ins\n"); 710 | return false; 711 | } else { 712 | ListEntry *mov1_entry = ListEntryCreate(mov1_ins); 713 | ListEntry *mov2_entry = ListEntryCreate(mov2_ins); 714 | ListEntry *mov3_entry = ListEntryCreate(mov3_ins); 715 | ListEntry *mov4_entry = ListEntryCreate(mov4_ins); 716 | ListEntry *add_entry = ListEntryCreate(add_ins); 717 | //add instructions to the list 718 | ListInsertAfter(list, current, mov1_entry); 719 | ListInsertAfter(list, mov1_entry, add_entry); 720 | ListInsertAfter(list, add_entry, mov2_entry); 721 | ListInsertAfter(list, mov2_entry, mov3_entry); 722 | ListInsertAfter(list, mov3_entry, mov4_entry); 723 | ListRemove(list, current); 724 | free(mem_size_indicator); 725 | free(mov1); 726 | free(mov2); 727 | free(mov3); 728 | free(mov4); 729 | free(add); 730 | optimized = true; 731 | } 732 | break; 733 | } 734 | //12 = POPF 735 | case 12: { 736 | // This instruction cannot be converted into a pair "MOV/SUB", I will handle it in this way: 737 | // 1) I will create a fake instruction "ADD ESP/RSP, 4/8" + "MOV EFLAGS, [MEM]" 738 | // 2) I will mark the instruction as INVALID, so other optimization methods can ignore it if needed 739 | //generating mnemonic & op_str 740 | cs_insn *mov = calloc(1, sizeof(cs_insn)); 741 | cs_insn *add = calloc(1, sizeof(cs_insn)); 742 | sprintf(mov->mnemonic, "mov"); 743 | sprintf(add->mnemonic, "add"); 744 | uint8_t dst_reg = (mode == CS_MODE_32) ? X86_REG_EAX : X86_REG_RAX; 745 | uint8_t esp_reg = (mode == CS_MODE_32) ? X86_REG_ESP : X86_REG_RSP; 746 | uint8_t displacement = (mode == CS_MODE_32) ? 4 : 8; 747 | sprintf(mov->op_str, "%s, [%s - %d]", cs_reg_name(handle, dst_reg), cs_reg_name(handle, esp_reg), displacement); 748 | sprintf(add->op_str, "%s, %d", cs_reg_name(handle, esp_reg), displacement); 749 | char *fake_op_str = calloc(40, sizeof(char)); 750 | sprintf(fake_op_str, "%s, [%s - %d]", cs_reg_name(handle, X86_REG_EFLAGS), cs_reg_name(handle, esp_reg), displacement); 751 | //generating new Instructions 752 | Instruction *mov_ins = assemble_fake_insn(mov->mnemonic, mov->op_str, fake_op_str, TEXT_ADDRESS, mode); 753 | Instruction *add_ins = assemble_insn(add->mnemonic, add->op_str, TEXT_ADDRESS, mode); 754 | //assemble FAKE instruction 755 | if(!mov_ins || !add_ins) { 756 | if(VERBOSE_ERROR) printf("[-] Error: reassemble() || update_disasm() - expand_stack_ins\n"); 757 | return false; 758 | } else { 759 | //fix eflags register 760 | mov_ins->insn->detail->x86.operands[0].reg = X86_REG_EFLAGS; 761 | ListEntry *mov_entry = ListEntryCreate(mov_ins); 762 | ListEntry *add_entry = ListEntryCreate(add_ins); 763 | //add instructions to the list 764 | ListInsertAfter(list, current, add_entry); 765 | ListInsertAfter(list, add_entry, mov_entry); 766 | free(fake_op_str); 767 | free(mov); 768 | free(add); 769 | optimized = true; 770 | } 771 | break; 772 | } 773 | //16 = POPAL 774 | case 16: { 775 | switch(mode) { 776 | case CS_MODE_32: { 777 | //I have to simulate the pop of: EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI 778 | cs_insn *mov_eax = calloc(1, sizeof(cs_insn)); 779 | cs_insn *mov_ecx = calloc(1, sizeof(cs_insn)); 780 | cs_insn *mov_edx = calloc(1, sizeof(cs_insn)); 781 | cs_insn *mov_ebx = calloc(1, sizeof(cs_insn)); 782 | cs_insn *mov_esp = calloc(1, sizeof(cs_insn)); 783 | cs_insn *mov_ebp = calloc(1, sizeof(cs_insn)); 784 | cs_insn *mov_esi = calloc(1, sizeof(cs_insn)); 785 | cs_insn *mov_edi = calloc(1, sizeof(cs_insn)); 786 | cs_insn *add = calloc(1, sizeof(cs_insn)); 787 | //generating mnemonic 788 | sprintf(mov_eax->mnemonic, "mov"); 789 | sprintf(mov_ecx->mnemonic, "mov"); 790 | sprintf(mov_edx->mnemonic, "mov"); 791 | sprintf(mov_ebx->mnemonic, "mov"); 792 | sprintf(mov_esp->mnemonic, "mov"); 793 | sprintf(mov_ebp->mnemonic, "mov"); 794 | sprintf(mov_esi->mnemonic, "mov"); 795 | sprintf(mov_edi->mnemonic, "mov"); 796 | sprintf(add->mnemonic, "add"); 797 | //generating op_str 798 | sprintf(add->op_str, "esp, 0x20"); 799 | sprintf(mov_edi->op_str, "edi, [esp-4]"); 800 | sprintf(mov_esi->op_str, "esi, [esp-8]"); 801 | sprintf(mov_ebp->op_str, "ebp, [esp-0xc]"); 802 | sprintf(mov_esp->op_str, "esp, [esp-0x10]"); 803 | sprintf(mov_ebx->op_str, "ebx, [esp-0x14]"); 804 | sprintf(mov_edx->op_str, "edx, [esp-0x18]"); 805 | sprintf(mov_ecx->op_str, "ecx, [esp-0x1c]"); 806 | sprintf(mov_eax->op_str, "eax, [esp-0x20]"); 807 | //generating new Instructions 808 | Instruction *mov_eax_ins = assemble_insn(mov_eax->mnemonic, mov_eax->op_str, TEXT_ADDRESS, mode); 809 | Instruction *mov_ecx_ins = assemble_insn(mov_ecx->mnemonic, mov_ecx->op_str, TEXT_ADDRESS, mode); 810 | Instruction *mov_edx_ins = assemble_insn(mov_edx->mnemonic, mov_edx->op_str, TEXT_ADDRESS, mode); 811 | Instruction *mov_ebx_ins = assemble_insn(mov_ebx->mnemonic, mov_ebx->op_str, TEXT_ADDRESS, mode); 812 | Instruction *mov_esp_ins = assemble_insn(mov_esp->mnemonic, mov_esp->op_str, TEXT_ADDRESS, mode); 813 | Instruction *mov_ebp_ins = assemble_insn(mov_ebp->mnemonic, mov_ebp->op_str, TEXT_ADDRESS, mode); 814 | Instruction *mov_esi_ins = assemble_insn(mov_esi->mnemonic, mov_esi->op_str, TEXT_ADDRESS, mode); 815 | Instruction *mov_edi_ins = assemble_insn(mov_edi->mnemonic, mov_edi->op_str, TEXT_ADDRESS, mode); 816 | Instruction *add_ins = assemble_insn(add->mnemonic, add->op_str, TEXT_ADDRESS, mode); 817 | //printf("original: %s %s\n", insn->mnemonic, insn->op_str); 818 | //printf("[%s %s]\n", add->mnemonic, add->op_str); 819 | //printf("[%s %s]\n", mov_eax->mnemonic, mov_eax->op_str); 820 | //printf("[%s %s]\n", mov_ecx->mnemonic, mov_ecx->op_str); 821 | //printf("[%s %s]\n", mov_edx->mnemonic, mov_edx->op_str); 822 | //printf("[%s %s]\n", mov_ebx->mnemonic, mov_ebx->op_str); 823 | //printf("[%s %s]\n", mov_esp->mnemonic, mov_esp->op_str); 824 | //printf("[%s %s]\n", mov_ebp->mnemonic, mov_ebp->op_str); 825 | //printf("[%s %s]\n", mov_esi->mnemonic, mov_esi->op_str); 826 | //printf("[%s %s]\n\n", mov_edi->mnemonic, mov_edi->op_str); 827 | //assemble instructions 828 | if(!mov_eax_ins || !mov_ebx_ins || !mov_ecx_ins || !mov_edx_ins || !mov_esp_ins || !mov_ebp_ins || !mov_esi_ins || !mov_edi_ins || !add_ins) { 829 | if(VERBOSE_ERROR) printf("[-] Error: reassemble() || update_disasm() - expand_stack_ins\n"); 830 | return false; 831 | } else { 832 | ListEntry *mov_eax_entry = ListEntryCreate(mov_eax_ins); 833 | ListEntry *mov_ecx_entry = ListEntryCreate(mov_ecx_ins); 834 | ListEntry *mov_edx_entry = ListEntryCreate(mov_edx_ins); 835 | ListEntry *mov_ebx_entry = ListEntryCreate(mov_ebx_ins); 836 | ListEntry *mov_esp_entry = ListEntryCreate(mov_esp_ins); 837 | ListEntry *mov_ebp_entry = ListEntryCreate(mov_ebp_ins); 838 | ListEntry *mov_esi_entry = ListEntryCreate(mov_esi_ins); 839 | ListEntry *mov_edi_entry = ListEntryCreate(mov_edi_ins); 840 | ListEntry *add_entry = ListEntryCreate(add_ins); 841 | //add instructions to the list 842 | ListInsertAfter(list, current, add_entry); 843 | ListInsertAfter(list, add_entry, mov_eax_entry); 844 | ListInsertAfter(list, mov_eax_entry, mov_ecx_entry); 845 | ListInsertAfter(list, mov_ecx_entry, mov_edx_entry); 846 | ListInsertAfter(list, mov_edx_entry, mov_ebx_entry); 847 | ListInsertAfter(list, mov_ebx_entry, mov_esp_entry); 848 | ListInsertAfter(list, mov_esp_entry, mov_ebp_entry); 849 | ListInsertAfter(list, mov_ebp_entry, mov_esi_entry); 850 | ListInsertAfter(list, mov_esi_entry, mov_edi_entry); 851 | ListRemove(list, current); 852 | free(mov_eax); 853 | free(mov_ecx); 854 | free(mov_edx); 855 | free(mov_ebx); 856 | free(mov_esp); 857 | free(mov_ebp); 858 | free(mov_esi); 859 | free(mov_edi); 860 | free(add); 861 | optimized = true; 862 | } 863 | break; 864 | } 865 | } 866 | break; 867 | } 868 | //17 = MOV REG, ESP/RSP 869 | case 17: { 870 | //generating mnemonic & op_str 871 | cs_insn *lea = calloc(1, sizeof(cs_insn)); 872 | sprintf(lea->mnemonic, "lea"); 873 | //find destination register 874 | uint8_t dst_reg = get_reg_at(current_insn, REG_FIRST); 875 | uint8_t esp_reg = (mode == CS_MODE_32) ? X86_REG_ESP : X86_REG_RSP; 876 | sprintf(lea->op_str, "%s, [%s]", cs_reg_name(handle, dst_reg), cs_reg_name(handle, esp_reg)); 877 | //generating new Instructions 878 | Instruction *lea_ins = assemble_insn(lea->mnemonic, lea->op_str, TEXT_ADDRESS, mode); 879 | //printf("%s %s\n\n", lea->mnemonic, lea->op_str); 880 | //assemble instructions 881 | if(!lea_ins) { 882 | if(VERBOSE_ERROR) printf("[-] Error: reassemble() || update_disasm() - expand_stack_ins\n"); 883 | return false; 884 | } else { 885 | ListEntry *lea_entry = ListEntryCreate(lea_ins); 886 | ListInsertAfter(list, current, lea_entry); 887 | ListRemove(list, current); 888 | free(lea); 889 | optimized = true; 890 | } 891 | break; 892 | } 893 | //18 = MOV [BASE+INDEX*SCALE+DISP], ESP/RSP 894 | case 18: { 895 | //extract index, scale, & displacement from the current instruction 896 | uint8_t base = get_base(current_insn); 897 | uint8_t index = get_index(current_insn); 898 | uint32_t disp; 899 | get_disp(current_insn, &disp); 900 | uint32_t scale; 901 | get_scale(current_insn, &scale); 902 | //generating mnemonic & op_str 903 | cs_insn *mov1 = calloc(1, sizeof(cs_insn)); 904 | cs_insn *lea = calloc(1, sizeof(cs_insn)); 905 | cs_insn *mov2 = calloc(1, sizeof(cs_insn)); 906 | cs_insn *mov3 = calloc(1, sizeof(cs_insn)); 907 | sprintf(mov1->mnemonic, "mov"); 908 | sprintf(lea->mnemonic, "lea"); 909 | sprintf(mov2->mnemonic, "mov"); 910 | sprintf(mov3->mnemonic, "mov"); 911 | //generating op_str 912 | uint8_t esp_reg = (mode == CS_MODE_32) ? X86_REG_ESP : X86_REG_RSP; 913 | uint8_t tmp_reg = (mode == CS_MODE_32) ? X86_REG_EAX : X86_REG_RAX; 914 | sprintf(mov1->op_str, "[%s - 0x%lx], %s", cs_reg_name(handle, esp_reg), STACK_DISPLACEMENT, cs_reg_name(handle, tmp_reg)); 915 | sprintf(lea->op_str, "%s, [%s]", cs_reg_name(handle, tmp_reg), cs_reg_name(handle, esp_reg)); 916 | sprintf(mov2->op_str, "[%s + %s * 0x%lx + 0x%lx], %s", cs_reg_name(handle, base), cs_reg_name(handle, index), scale, disp, cs_reg_name(handle, tmp_reg)); 917 | sprintf(mov3->op_str, "%s, [%s - 0x%lx]", cs_reg_name(handle, tmp_reg), cs_reg_name(handle, esp_reg), STACK_DISPLACEMENT); 918 | //generating new Instructions 919 | Instruction *mov1_ins = assemble_insn(mov1->mnemonic, mov1->op_str, TEXT_ADDRESS, mode); 920 | Instruction *lea_ins = assemble_insn(lea->mnemonic, lea->op_str, TEXT_ADDRESS, mode); 921 | Instruction *mov2_ins = assemble_insn(mov2->mnemonic, mov2->op_str, TEXT_ADDRESS, mode); 922 | Instruction *mov3_ins = assemble_insn(mov3->mnemonic, mov3->op_str, TEXT_ADDRESS, mode); 923 | //printf("original: %s %s\n", insn->mnemonic, insn->op_str); 924 | //printf("%s %s\n", mov1->mnemonic, mov1->op_str); 925 | //printf("%s %s\n", lea->mnemonic, lea->op_str); 926 | //printf("%s %s\n", mov2->mnemonic, mov2->op_str); 927 | //printf("%s %s\n\n", mov3->mnemonic, mov3->op_str); 928 | //assemble instructions 929 | if(!mov1_ins || !mov2_ins || !mov3_ins || !lea_ins) { 930 | if(VERBOSE_ERROR) printf("[-] Error: reassemble() || update_disasm() - expand_stack_ins\n"); 931 | return false; 932 | } else { 933 | //add instructions to the list 934 | ListEntry *mov1_entry = ListEntryCreate(mov1_ins); 935 | ListEntry *mov2_entry = ListEntryCreate(mov2_ins); 936 | ListEntry *mov3_entry = ListEntryCreate(mov3_ins); 937 | ListEntry *lea_entry = ListEntryCreate(lea_ins); 938 | ListInsertAfter(list, current, mov1_entry); 939 | ListInsertAfter(list, mov1_entry, lea_entry); 940 | ListInsertAfter(list, lea_entry, mov2_entry); 941 | ListInsertAfter(list, mov2_entry, mov3_entry); 942 | ListRemove(list, current); 943 | free(mov1); 944 | free(mov2); 945 | free(mov3); 946 | free(lea); 947 | optimized = true; 948 | } 949 | break; 950 | } 951 | //19 = XCHG [BASE+INDEX*SCALE+DISP], REG 952 | case 19: { 953 | //find destination register 954 | uint8_t reg = X86_REG_INVALID, base = X86_REG_INVALID, index = X86_REG_INVALID; 955 | uint32_t scale = 1, disp = 0; 956 | uint64_t old_address = current_insn->insn->address; 957 | x86 = &(insn->detail->x86); 958 | op_count = x86->op_count; 959 | for(size_t i = 0; i < op_count; i++) { 960 | op = &(x86->operands[i]); 961 | if(op->type == X86_OP_REG && op->reg != X86_REG_INVALID && (op->reg != X86_REG_ESP && op->reg != X86_REG_RSP)) { 962 | reg = op->reg; 963 | } else if(op->type == X86_OP_MEM) { 964 | base = op->mem.base; 965 | index = op->mem.index; 966 | scale = (uint32_t)op->mem.scale; 967 | disp = (uint32_t)op->mem.disp; 968 | } 969 | } 970 | //choose temporary register 971 | uint8_t temp_reg = X86_REG_INVALID; 972 | switch(mode) { 973 | case CS_MODE_32: 974 | temp_reg = (reg == X86_REG_EAX) ? X86_REG_EBX : X86_REG_EAX; 975 | break; 976 | case CS_MODE_64: 977 | temp_reg = (reg == X86_REG_RAX) ? X86_REG_RBX : X86_REG_RAX; 978 | break; 979 | } 980 | //generating mnemonic & op_str 981 | cs_insn *mov1 = calloc(1, sizeof(cs_insn)); 982 | cs_insn *mov2 = calloc(1, sizeof(cs_insn)); 983 | cs_insn *mov3 = calloc(1, sizeof(cs_insn)); 984 | cs_insn *mov4 = calloc(1, sizeof(cs_insn)); 985 | cs_insn *mov5 = calloc(1, sizeof(cs_insn)); 986 | sprintf(mov1->mnemonic, "mov"); 987 | sprintf(mov2->mnemonic, "mov"); 988 | sprintf(mov3->mnemonic, "mov"); 989 | sprintf(mov4->mnemonic, "mov"); 990 | sprintf(mov5->mnemonic, "mov"); 991 | uint8_t esp_reg = (mode == CS_MODE_32) ? X86_REG_ESP : X86_REG_RSP; 992 | sprintf(mov1->op_str, "[%s - 0x%lx], %s", cs_reg_name(handle, esp_reg), STACK_DISPLACEMENT, cs_reg_name(handle, temp_reg)); 993 | sprintf(mov2->op_str, "%s, [%s + %s * 0x%lx + 0x%lx]", cs_reg_name(handle, temp_reg), cs_reg_name(handle, base), cs_reg_name(handle, index), scale, disp); 994 | sprintf(mov3->op_str, "[%s + %s * 0x%lx + 0x%lx], %s", cs_reg_name(handle, base), cs_reg_name(handle, index), scale, disp, cs_reg_name(handle, reg)); 995 | sprintf(mov4->op_str, "%s, %s", cs_reg_name(handle, reg), cs_reg_name(handle, temp_reg)); 996 | sprintf(mov5->op_str, "%s, [%s - 0x%lx]", cs_reg_name(handle, temp_reg), cs_reg_name(handle, esp_reg), STACK_DISPLACEMENT); 997 | //generating new Instructions 998 | Instruction *mov1_ins = assemble_insn(mov1->mnemonic, mov1->op_str, TEXT_ADDRESS, mode); 999 | Instruction *mov2_ins = assemble_insn(mov2->mnemonic, mov2->op_str, TEXT_ADDRESS, mode); 1000 | Instruction *mov3_ins = assemble_insn(mov3->mnemonic, mov3->op_str, TEXT_ADDRESS, mode); 1001 | Instruction *mov4_ins = assemble_insn(mov4->mnemonic, mov4->op_str, TEXT_ADDRESS, mode); 1002 | Instruction *mov5_ins = assemble_insn(mov5->mnemonic, mov5->op_str, TEXT_ADDRESS, mode); 1003 | //printf("%s %s\n", mov1->mnemonic, mov1->op_str); 1004 | //printf("%s %s\n", mov2->mnemonic, mov2->op_str); 1005 | //printf("%s %s\n", mov3->mnemonic, mov3->op_str); 1006 | //printf("%s %s\n", mov4->mnemonic, mov4->op_str); 1007 | //printf("%s %s\n\n", mov5->mnemonic, mov5->op_str); 1008 | //assemble instructions 1009 | if(!mov1_ins || !mov2_ins || !mov3_ins || !mov4_ins || !mov5_ins) { 1010 | if(VERBOSE_ERROR) printf("[-] Error: reassemble() || update_disasm() - expand_stack_ins\n"); 1011 | return false; 1012 | } else { 1013 | //update addresses 1014 | mov1_ins->insn->address = old_address++; 1015 | mov2_ins->insn->address = old_address++; 1016 | mov3_ins->insn->address = old_address++; 1017 | mov4_ins->insn->address = old_address++; 1018 | mov5_ins->insn->address = old_address; 1019 | //create ListEntry 1020 | ListEntry *mov1_entry = ListEntryCreate(mov1_ins); 1021 | ListEntry *mov2_entry = ListEntryCreate(mov2_ins); 1022 | ListEntry *mov3_entry = ListEntryCreate(mov3_ins); 1023 | ListEntry *mov4_entry = ListEntryCreate(mov4_ins); 1024 | ListEntry *mov5_entry = ListEntryCreate(mov5_ins); 1025 | //add instructions to the list 1026 | ListInsertAfter(list, current, mov1_entry); 1027 | ListInsertAfter(list, mov1_entry, mov2_entry); 1028 | ListInsertAfter(list, mov2_entry, mov3_entry); 1029 | ListInsertAfter(list, mov3_entry, mov4_entry); 1030 | ListInsertAfter(list, mov4_entry, mov5_entry); 1031 | ListRemove(list, current); 1032 | free(mov1); 1033 | free(mov2); 1034 | free(mov3); 1035 | free(mov4); 1036 | free(mov5); 1037 | optimized = true; 1038 | } 1039 | break; 1040 | } 1041 | //20 = XCHG REG1, REG2 1042 | case 20: { 1043 | //find source & destination registers 1044 | uint8_t src_reg = X86_REG_INVALID, dst_reg = X86_REG_INVALID; 1045 | uint64_t old_address = current_insn->insn->address; 1046 | x86 = &(insn->detail->x86); 1047 | op_count = x86->op_count; 1048 | for(size_t i = 0; i < op_count; i++) { 1049 | op = &(x86->operands[i]); 1050 | if(op->type == X86_OP_REG && op->reg != X86_REG_INVALID && (op->reg != X86_REG_ESP && op->reg != X86_REG_RSP)) { 1051 | if(dst_reg == X86_REG_INVALID) { 1052 | //extract destination reg 1053 | dst_reg = op->reg; 1054 | } else { 1055 | //extract source reg 1056 | src_reg = op->reg; 1057 | } 1058 | } 1059 | } 1060 | //check if src_reg == dst_reg, in this case 1061 | //generating mnemonic & op_str 1062 | cs_insn *mov1 = calloc(1, sizeof(cs_insn)); 1063 | cs_insn *mov2 = calloc(1, sizeof(cs_insn)); 1064 | cs_insn *mov3 = calloc(1, sizeof(cs_insn)); 1065 | sprintf(mov1->mnemonic, "mov"); 1066 | sprintf(mov2->mnemonic, "mov"); 1067 | sprintf(mov3->mnemonic, "mov"); 1068 | uint8_t esp_reg = (mode == CS_MODE_32) ? X86_REG_ESP : X86_REG_RSP; 1069 | sprintf(mov1->op_str, "[%s - 0x%lx], %s", cs_reg_name(handle, esp_reg), STACK_DISPLACEMENT, cs_reg_name(handle, src_reg)); 1070 | sprintf(mov2->op_str, "%s, %s", cs_reg_name(handle, src_reg), cs_reg_name(handle, dst_reg)); 1071 | sprintf(mov3->op_str, "%s, [%s - 0x%lx]", cs_reg_name(handle, dst_reg), cs_reg_name(handle, esp_reg), STACK_DISPLACEMENT); 1072 | //generating new Instructions 1073 | Instruction *mov1_ins = assemble_insn(mov1->mnemonic, mov1->op_str, TEXT_ADDRESS, mode); 1074 | Instruction *mov2_ins = assemble_insn(mov2->mnemonic, mov2->op_str, TEXT_ADDRESS, mode); 1075 | Instruction *mov3_ins = assemble_insn(mov3->mnemonic, mov3->op_str, TEXT_ADDRESS, mode); 1076 | //printf("%s %s\n", mov1->mnemonic, mov1->op_str); 1077 | //printf("%s %s\n", mov2->mnemonic, mov2->op_str); 1078 | //printf("%s %s\n\n", mov3->mnemonic, mov3->op_str); 1079 | if(!mov1_ins || !mov2_ins || !mov3_ins) { 1080 | if(VERBOSE_ERROR) printf("[-] Error: reassemble() || update_disasm() - expand_stack_ins\n"); 1081 | return false; 1082 | } else { 1083 | //update addresses 1084 | mov1_ins->insn->address = old_address++; 1085 | mov2_ins->insn->address = old_address++; 1086 | mov3_ins->insn->address = old_address; 1087 | //create ListEntry 1088 | ListEntry *mov1_entry = ListEntryCreate(mov1_ins); 1089 | ListEntry *mov2_entry = ListEntryCreate(mov2_ins); 1090 | ListEntry *mov3_entry = ListEntryCreate(mov3_ins); 1091 | //add instructions to the list 1092 | ListInsertAfter(list, current, mov1_entry); 1093 | ListInsertAfter(list, mov1_entry, mov2_entry); 1094 | ListInsertAfter(list, mov2_entry, mov3_entry); 1095 | ListRemove(list, current); 1096 | free(mov1); 1097 | free(mov2); 1098 | free(mov3); 1099 | optimized = true; 1100 | } 1101 | break; 1102 | } 1103 | //21 = LEA REG, [BASE+INDEX*SCALE+DISP] 1104 | case 21: { 1105 | cs_x86 *x86 = &(current_insn->insn->detail->x86); 1106 | cs_x86_op *op; 1107 | size_t op_count = x86->op_count; 1108 | //extract useful information 1109 | uint8_t reg = X86_REG_INVALID, base = X86_REG_INVALID, index = X86_REG_INVALID; 1110 | uint32_t scale = 1, disp = 0; 1111 | for(size_t i = 0; i < op_count; i++) { 1112 | op = &(x86->operands[i]); 1113 | if(op->type == X86_OP_REG && op->access == CS_AC_WRITE) { 1114 | reg = op->reg; 1115 | } else if(op->type == X86_OP_MEM && op->access == CS_AC_READ) { 1116 | base = op->mem.base; 1117 | index = op->mem.index; 1118 | scale = (uint32_t)op->mem.scale; 1119 | disp = (uint32_t)op->mem.disp; 1120 | } 1121 | } 1122 | if(!is_same_register_type(base, X86_REG_RSP) && !is_same_register_type(index, X86_REG_RSP) && !is_same_register_type(base, X86_REG_RIP) && !is_same_register_type(index, X86_REG_RIP)) { 1123 | //create new instructions for expansion 1124 | if(base != X86_REG_INVALID && index != X86_REG_INVALID) { 1125 | //printf("Found: lea reg, [reg1 + reg2*scale + disp]: %s %s\n", current->insn->mnemonic, current->insn->op_str); 1126 | //Need to implement: 1127 | //shl index, scale 1128 | //add base, index 1129 | //add base, disp 1130 | //mov reg, base 1131 | if(scale != 1) { 1132 | //shl index, scale 1133 | Instruction *shl_ins = calloc(1, sizeof(Instruction)); 1134 | shl_ins->insn = calloc(1, sizeof(cs_insn)); 1135 | sprintf(shl_ins->insn->mnemonic, "shl"); 1136 | //in this case the 'scale' value can be: 0x2 (0x1), 0x4 (0x2), 0x8 (0x3) 1137 | switch(scale) { 1138 | case 0x2: 1139 | scale = 1; 1140 | break; 1141 | case 0x4: 1142 | scale = 2; 1143 | break; 1144 | case 0x8: 1145 | scale = 3; 1146 | break; 1147 | } 1148 | sprintf(shl_ins->insn->op_str, "%s, 0x%lx", cs_reg_name(handle, index), scale); 1149 | if(!(reassemble(shl_ins, mode) && update_disasm(shl_ins, TEXT_ADDRESS, mode))) { 1150 | if(VERBOSE_ERROR) printf("[-] Error: reassemble() || update_disasm() - expand_stack_ins\n"); 1151 | } else { 1152 | //printf("SHL: %s %s\n", shl_ins->insn->mnemonic, shl_ins->insn->op_str); 1153 | ListEntry *shl_entry = ListEntryCreate(shl_ins); 1154 | ListInsertBefore(list, current, shl_entry); 1155 | } 1156 | } 1157 | ListEntry *add_entry_1; 1158 | Instruction *add_ins_1 = calloc(1, sizeof(Instruction)); 1159 | add_ins_1->insn = calloc(1, sizeof(cs_insn)); 1160 | sprintf(add_ins_1->insn->mnemonic, "add"); 1161 | sprintf(add_ins_1->insn->op_str, "%s, %s", cs_reg_name(handle, base), cs_reg_name(handle, index)); 1162 | if(!(reassemble(add_ins_1, mode) && update_disasm(add_ins_1, TEXT_ADDRESS, mode))) { 1163 | if(VERBOSE_ERROR) printf("[-] Error: reassemble() || update_disasm() - expand_stack_ins\n"); 1164 | } else { 1165 | //printf("ADD: %s %s\n", add_ins_1->insn->mnemonic, add_ins_1->insn->op_str); 1166 | ListEntry *add_entry_1 = ListEntryCreate(add_ins_1); 1167 | ListInsertAfter(list, current, add_entry_1); 1168 | } 1169 | if(disp != 0) { 1170 | Instruction *add_ins_2 = calloc(1, sizeof(Instruction)); 1171 | add_ins_2->insn = calloc(1, sizeof(cs_insn)); 1172 | sprintf(add_ins_2->insn->mnemonic, "add"); 1173 | sprintf(add_ins_2->insn->op_str, "%s, 0x%lx", cs_reg_name(handle, base), disp); 1174 | if(!(reassemble(add_ins_2, mode) && update_disasm(add_ins_2, TEXT_ADDRESS, mode))) { 1175 | if(VERBOSE_ERROR) printf("[-] Error: reassemble() || update_disasm() - expand_stack_ins\n"); 1176 | } else { 1177 | //printf("ADD: %s %s\n", add_ins_2->insn->mnemonic, add_ins_2->insn->op_str); 1178 | ListEntry *add_entry_2 = ListEntryCreate(add_ins_2); 1179 | ListInsertAfter(list, add_entry_1, add_entry_2); 1180 | } 1181 | } 1182 | Instruction *mov_ins = calloc(1, sizeof(Instruction)); 1183 | mov_ins->insn = calloc(1, sizeof(cs_insn)); 1184 | sprintf(mov_ins->insn->mnemonic, "mov"); 1185 | sprintf(mov_ins->insn->op_str, "%s, %s", cs_reg_name(handle, reg), cs_reg_name(handle, base)); 1186 | if(!(reassemble(mov_ins, mode) && update_disasm(mov_ins, TEXT_ADDRESS, mode))) { 1187 | if(VERBOSE_ERROR) printf("[-] Error: reassemble() || update_disasm() - expand_stack_ins\n"); 1188 | } else { 1189 | //printf("MOV: %s %s\n", mov_ins->insn->mnemonic, mov_ins->insn->op_str); 1190 | ListEntry *mov_entry = ListEntryCreate(mov_ins); 1191 | ListInsertBefore(list, current->next, mov_entry); 1192 | } 1193 | ListRemove(list, current); 1194 | optimized = true; 1195 | } else if(base != X86_REG_INVALID) { 1196 | //printf("Found: lea reg, [reg1 + disp]: %s %s\n", current->insn->mnemonic, current->insn->op_str); 1197 | //Need to implement 1198 | //add base, disp 1199 | //mov reg, base 1200 | if(disp != 0) { 1201 | Instruction *add_ins_2 = calloc(1, sizeof(Instruction)); 1202 | add_ins_2->insn = calloc(1, sizeof(cs_insn)); 1203 | sprintf(add_ins_2->insn->mnemonic, "add"); 1204 | sprintf(add_ins_2->insn->op_str, "%s, 0x%lx", cs_reg_name(handle, base), disp); 1205 | if(!(reassemble(add_ins_2, mode) && update_disasm(add_ins_2, TEXT_ADDRESS, mode))) { 1206 | if(VERBOSE_ERROR) printf("[-] Error: reassemble() || update_disasm() - expand_stack_ins\n"); 1207 | } else { 1208 | //printf("ADD: %s %s\n", add_ins_2->insn->mnemonic, add_ins_2->insn->op_str); 1209 | ListEntry *add_entry_2 = ListEntryCreate(add_ins_2); 1210 | ListInsertBefore(list, current, add_entry_2); 1211 | } 1212 | } 1213 | Instruction *mov_ins = calloc(1, sizeof(Instruction)); 1214 | mov_ins->insn = calloc(1, sizeof(cs_insn)); 1215 | sprintf(mov_ins->insn->mnemonic, "mov"); 1216 | sprintf(mov_ins->insn->op_str, "%s, %s", cs_reg_name(handle, reg), cs_reg_name(handle, base)); 1217 | if(!(reassemble(mov_ins, mode) && update_disasm(mov_ins, TEXT_ADDRESS, mode))) { 1218 | if(VERBOSE_ERROR) printf("[-] Error: reassemble() || update_disasm() - expand_stack_ins\n"); 1219 | } else { 1220 | //printf("MOV: %s %s\n", mov_ins->insn->mnemonic, mov_ins->insn->op_str); 1221 | //ListInsertAfter(list, current, mov_ins); 1222 | uint64_t old_address = insn->address; 1223 | memcpy(insn, mov_ins->insn, sizeof(cs_insn)); 1224 | insn->address = old_address; 1225 | //ListRemove(list, current); 1226 | optimized = true; 1227 | } 1228 | } else if(index != X86_REG_INVALID) { 1229 | //printf("Found: lea reg, [reg2*scale + disp]: %s %s\n", current->insn->mnemonic, current->insn->op_str); 1230 | //Need to implement 1231 | //shl index, scale 1232 | //add index, disp 1233 | //mov reg, index 1234 | Instruction *shl_ins; 1235 | ListEntry *shl_entry; 1236 | if(scale != 1) { 1237 | //shl index, scale 1238 | shl_ins = calloc(1, sizeof(Instruction)); 1239 | shl_ins->insn = calloc(1, sizeof(cs_insn)); 1240 | sprintf(shl_ins->insn->mnemonic, "shl"); 1241 | //in this case the 'scale' value can be: 0x2 (0x1), 0x4 (0x2), 0x8 (0x3) 1242 | switch(scale) { 1243 | case 0x2: 1244 | scale = 1; 1245 | break; 1246 | case 0x4: 1247 | scale = 2; 1248 | break; 1249 | case 0x8: 1250 | scale = 3; 1251 | break; 1252 | } 1253 | sprintf(shl_ins->insn->op_str, "%s, 0x%lx", cs_reg_name(handle, index), scale); 1254 | if(!(reassemble(shl_ins, mode) && update_disasm(shl_ins, TEXT_ADDRESS, mode))) { 1255 | if(VERBOSE_ERROR) printf("[-] Error: reassemble() || update_disasm() - expand_stack_ins\n"); 1256 | } else { 1257 | //printf("SHL: %s %s\n", shl_ins->insn->mnemonic, shl_ins->insn->op_str); 1258 | shl_entry = ListEntryCreate(shl_ins); 1259 | ListInsertBefore(list, current, shl_entry); 1260 | } 1261 | } 1262 | if(disp != 0) { 1263 | Instruction *add_ins_2 = calloc(1, sizeof(Instruction)); 1264 | add_ins_2->insn = calloc(1, sizeof(cs_insn)); 1265 | sprintf(add_ins_2->insn->mnemonic, "add"); 1266 | sprintf(add_ins_2->insn->op_str, "%s, 0x%lx", cs_reg_name(handle, index), disp); 1267 | if(!(reassemble(add_ins_2, mode) && update_disasm(add_ins_2, TEXT_ADDRESS, mode))) { 1268 | if(VERBOSE_ERROR) printf("[-] Error: reassemble() || update_disasm() - expand_stack_ins\n"); 1269 | } else { 1270 | //printf("ADD: %s %s\n", add_ins_2->insn->mnemonic, add_ins_2->insn->op_str); 1271 | if(shl_ins == NULL) { 1272 | ListEntry *add_entry_2 = ListEntryCreate(add_ins_2); 1273 | ListInsertBefore(list, current, add_entry_2); 1274 | } else { 1275 | ListEntry *add_entry_2 = ListEntryCreate(add_ins_2); 1276 | ListInsertAfter(list, shl_entry, add_entry_2); 1277 | } 1278 | } 1279 | } 1280 | Instruction *mov_ins = calloc(1, sizeof(Instruction)); 1281 | mov_ins->insn = calloc(1, sizeof(cs_insn)); 1282 | sprintf(mov_ins->insn->mnemonic, "mov"); 1283 | sprintf(mov_ins->insn->op_str, "%s, %s", cs_reg_name(handle, reg), cs_reg_name(handle, index)); 1284 | if(!(reassemble(mov_ins, mode) && update_disasm(mov_ins, TEXT_ADDRESS, mode))) { 1285 | if(VERBOSE_ERROR) printf("[-] Error: reassemble() || update_disasm() - expand_stack_ins\n"); 1286 | } else { 1287 | //printf("MOV: %s %s\n", mov_ins->insn->mnemonic, mov_ins->insn->op_str); 1288 | ListEntry *mov_entry = ListEntryCreate(mov_ins); 1289 | ListInsertAfter(list, current, mov_entry); 1290 | } 1291 | ListRemove(list, current); 1292 | optimized = true; 1293 | } 1294 | } 1295 | break; 1296 | } 1297 | } 1298 | current = next; 1299 | } 1300 | return optimized; 1301 | } 1302 | 1303 | /* ------------------------------------------------------------------------------------------------------------------ */ 1304 | 1305 | /* 1306 | Name: update_add_sub 1307 | Description: this function calculates the new value of a sub/add instruction an saves it on imm3; 1308 | it returns also the ID for the updated instruction, ADD or SUB. 1309 | */ 1310 | static uint32_t update_add_sub(bool is_add_1, uint64_t imm1, bool is_add_2, uint64_t imm2, uint64_t *imm3) { 1311 | bool is_add; 1312 | if(is_add_1 == is_add_2) { 1313 | *imm3 = imm1 + imm2; 1314 | is_add = is_add_1; 1315 | } else { 1316 | if(is_add_1 && !is_add_2) { 1317 | if((int64_t)imm1 > (int64_t)imm2) { 1318 | *imm3 = imm1 - imm2; 1319 | is_add = is_add_1; 1320 | } else { 1321 | *imm3 = imm2 - imm1; 1322 | is_add = is_add_2; 1323 | } 1324 | } else { 1325 | if((int64_t)imm1 > (int64_t)imm2) { 1326 | *imm3 = imm1 - imm2; 1327 | is_add = is_add_1; 1328 | } else { 1329 | *imm3 = imm2 - imm1; 1330 | is_add = is_add_2; 1331 | } 1332 | } 1333 | } 1334 | return (is_add) ? X86_INS_ADD : X86_INS_SUB; 1335 | } 1336 | 1337 | /* 1338 | Name: collapse_add_sub 1339 | Description: this function is used to collapse add & sub 1340 | instructions on registers & memory locations, for example: 1341 | add reg, 0x2 add [mem], 0x4 1342 | sub reg, 0x4 sub [mem], 0x2 1343 | ------------ -------------- 1344 | sub reg, 0x2 add [mem], 0x2 1345 | It is possible to semplificate also the following case, 1346 | because add/sub operations are not interfering: 1347 | add reg1, 0x4 1348 | add reg1, reg2 1349 | sub reg1, 0x2 1350 | ------------- 1351 | add reg1, reg2 1352 | add reg1, 0x2 1353 | In the collapse operation must stop when the register or the 1354 | memory location is accessed by an instruction different from 1355 | add or sub, for example: 1356 | add reg, 0x4 1357 | xor reg, 0x7 1358 | sub reg, 0x2 1359 | The xor operation blocks the collapse. 1360 | The memory collapse must stop also when 'base'/'index' are 1361 | modified during propagation. 1362 | */ 1363 | bool collapse_add_sub(csh handle, List *list, uint8_t mode) { 1364 | bool optimized = false; 1365 | //check if the list is empty 1366 | if(!list->first) return false; 1367 | ListEntry *current = list->first, *next; 1368 | //mask for general ADD REG, IMM match 1369 | InsnMatch add_reg = { .id = X86_INS_ADD, .type = X86_DST_REG_SRC_IMM }; 1370 | //mask for general ADD [MEM], IMM match 1371 | InsnMatch add_mem = { .id = X86_INS_ADD, .type = X86_DST_MEM_SRC_IMM }; 1372 | //mask for general SUB REG, IMM 1373 | InsnMatch sub_reg = { .id = X86_INS_SUB, .type = X86_DST_REG_SRC_IMM }; 1374 | //mask for general SUB [MEM], IMM 1375 | InsnMatch sub_mem = { .id = X86_INS_SUB, .type = X86_DST_MEM_SRC_IMM }; 1376 | //pointers to add/sub instructions 1377 | ListEntry *reg_before, *mem_before, *first; 1378 | Instruction *first_insn; 1379 | while(current) { 1380 | //check who comes first between add_reg - sub_reg & add_mem - sub_mem 1381 | reg_before = ListIsBefore(find_insn(current, NULL, &add_reg), find_insn(current, NULL, &sub_reg)); 1382 | mem_before = ListIsBefore(find_insn(current, NULL, &add_mem), find_insn(current, NULL, &sub_mem)); 1383 | //check who comes first between reg_before & mem_before 1384 | first = ListIsBefore(reg_before, mem_before); 1385 | if(!first/* || first == list->last*/) { 1386 | //The are no more add/sub instructions involving immediates in the code 1387 | if(VERBOSE) printf("[I] collapse_add_sub end!\n"); 1388 | break; 1389 | } 1390 | //extract Instruction from ListEntry 1391 | first_insn = (Instruction *)first->content; 1392 | if(VERBOSE) print_insn("\n[I] The ADD/SUB instruction is: ", first_insn); 1393 | //the next search will start right after this 'first' instruction 1394 | next = first->next; 1395 | if(is_memory_insn(first_insn)) { 1396 | //this is a memory instruction, need to understand how to handle the case: 1397 | //add [mem], imm 1398 | //sub [mem], imm 1399 | } else { 1400 | //this is a register instruction, extract the destination register and the immediate 1401 | uint8_t reg = get_reg_at(first_insn, REG_FIRST); 1402 | uint64_t imm; 1403 | bool imm_found = get_imm(first_insn, &imm); 1404 | //check if the register & imm are valid 1405 | if(is_valid(reg) && imm_found) { 1406 | //the instruction is valid, check if the mnemonic is add or sub 1407 | bool is_add = (cmp_id(first_insn->insn->id, X86_INS_ADD)) ? true : false; 1408 | ListEntry *next_use = first; 1409 | Instruction *instruction; 1410 | InsnAccess reg_access = { .reg = reg, .op_type = X86_OP_REG }; 1411 | //find the next instruction using REG 1412 | while(next_use && next_use->next && (next_use = find_insn_op_general_access(next_use->next, NULL, ®_access))) { 1413 | instruction = (Instruction *)next_use->content; 1414 | //check if the instruction is a memory instruction 1415 | if(is_memory_insn(instruction)) { 1416 | if(VERBOSE) print_insn("[I] mem: ", instruction); 1417 | uint8_t base = get_base(instruction); 1418 | uint8_t index = get_index(instruction); 1419 | uint8_t dst_reg = get_reg_at(instruction, REG_FIRST); 1420 | uint8_t src_reg = get_reg_at(instruction, REG_SECOND); 1421 | uint32_t id = get_id(instruction); 1422 | //check if 'reg' is used as index, terminate loop 1423 | if(is_same_register_type(index, reg) && !is_same_register_type(base, reg)) { 1424 | next_use = NULL; 1425 | } else if(is_same_register_type(base, reg)) { 1426 | //check if 'reg' is used as base, update disp in case 1427 | //update the displacement 1428 | uint32_t disp; 1429 | get_disp(instruction, &disp); 1430 | uint64_t imm3; 1431 | uint32_t new_opcode = update_add_sub(is_add, imm, true, disp, &imm3); 1432 | disp = (new_opcode == X86_INS_ADD) ? (uint32_t)imm3 : (uint32_t)(-imm3); 1433 | //update the instruction 1434 | if(set_disp(instruction, disp)) { 1435 | //reassemble the instruction 1436 | /*Instruction *updated = update_insn_str(handle, instruction, mode); 1437 | ListChangeEntry(next_use, updated); 1438 | //move 'first' instruction under the updated memory instruction and start again 1439 | ListRemove(list, first); 1440 | ListInsertAfter(list, next_use, first); 1441 | printf("AFTER\n"); 1442 | print_disassembly(handle, list, INFO); 1443 | if(VERBOSE && next_use) print_insn("next_use: ", next_use->content); 1444 | if(VERBOSE && next_use->next) print_insn("next_use->next: ", next_use->next->content); 1445 | if(VERBOSE && next_use->prev) print_insn("next_use->prev: ", next_use->prev->content); 1446 | if(VERBOSE && first) print_insn("next_use: ", first->content); 1447 | if(VERBOSE && first->next) print_insn("first->next: ", first->next->content); 1448 | if(VERBOSE && first->prev) print_insn("first->prev: ", first->prev->content); 1449 | //mark as optimized & start a new loop 1450 | optimized = true; 1451 | //stop here if the end is reached 1452 | /*if(first->next == list->last) { 1453 | first->next = NULL; 1454 | return optimized; 1455 | }*/ 1456 | //next_use = NULL; 1457 | } else { 1458 | printf("[!] Error while setting displacement, exit!\n"); 1459 | ExitProcess(EXIT_FAILURE); 1460 | } 1461 | } 1462 | //check if the source or destination register is equal to 'reg' 1463 | if(is_same_register_type(reg, dst_reg)) { 1464 | //in particular check for MOV overwrite, in this case delete also 'first' 1465 | if(cmp_id(id, X86_INS_MOV)) { 1466 | print_insn("OVERWRITE: ", first_insn); 1467 | ListRemove(list, first); 1468 | free(first->content); 1469 | } 1470 | //check if 'reg' is used as destination, terminate loop 1471 | next_use = NULL; 1472 | } else if(is_same_register_type(reg, src_reg)) { 1473 | print_insn("READ: ", first_insn); 1474 | next_use = NULL; 1475 | } 1476 | } else { 1477 | //check if the instruction is ADD/SUB 1478 | if(cmp_id(instruction->insn->id, X86_INS_ADD) || cmp_id(instruction->insn->id, X86_INS_SUB)) { 1479 | //found an add/sub instruction, check if the destination register is 'reg' 1480 | if(is_same_register_type(get_reg_at(instruction, REG_FIRST), reg)) { 1481 | //check if it is using an imm value 1482 | uint64_t tmp_imm; 1483 | if(get_imm(instruction, &tmp_imm)) { 1484 | if(VERBOSE) print_insn("[I] reg->add/sub->imm: ", instruction); 1485 | //update the immediate 1486 | bool is_add_2 = (cmp_id(instruction->insn->id, X86_INS_ADD)) ? true : false; 1487 | uint32_t new_opcode = update_add_sub(is_add, imm, is_add_2, tmp_imm, &tmp_imm); 1488 | tmp_imm = resize_immediate(tmp_imm, get_reg_at(instruction, REG_FIRST)); 1489 | //check if tmp_imm is 0 1490 | if(tmp_imm == 0) { 1491 | //remove the original & current instruction 1492 | printf("[I] Zero immediate!\n"); 1493 | print_insn("[I] Delete: ", first_insn); 1494 | print_insn("[I] Delete: ", instruction); 1495 | ListRemove(list, first); 1496 | free(first->content); 1497 | ListRemove(list, next_use); 1498 | free(next_use->content); 1499 | //mark the list as updated 1500 | optimized = true; 1501 | //terminate loop 1502 | next_use = NULL; 1503 | } else { 1504 | //update the instruction 1505 | if(set_imm(instruction, tmp_imm)) { 1506 | //set the new ID 1507 | set_id(instruction, new_opcode); 1508 | //reassemble the instruction 1509 | Instruction *updated = update_insn_str(handle, instruction, mode); 1510 | ListChangeEntry(next_use, updated); 1511 | //remove the original instruction 1512 | if(first) { 1513 | ListRemove(list, first); 1514 | free(first->content); 1515 | free(first); 1516 | //mark the list as updated 1517 | optimized = true; 1518 | //terminate loop 1519 | next_use = NULL; 1520 | } 1521 | } else { 1522 | printf("[!] Error while setting immediate, exit!\n"); 1523 | ExitProcess(EXIT_FAILURE); 1524 | } 1525 | } 1526 | } else { 1527 | //ignore this instruction 1528 | if(VERBOSE) print_insn("[I] reg->add/sub->other: ", instruction); 1529 | } 1530 | } else { 1531 | if(VERBOSE) print_insn("[I] reg->other: ", instruction); 1532 | //found an instruction reading 'reg', terminate loop 1533 | next_use = NULL; 1534 | } 1535 | } else { 1536 | if(VERBOSE) print_insn("[I] reg->other: ", instruction); 1537 | //found an instruction different from ADD/SUB, terminate loop 1538 | next_use = NULL; 1539 | } 1540 | } 1541 | } 1542 | } 1543 | } 1544 | current = next; 1545 | } 1546 | return optimized; 1547 | } 1548 | 1549 | /* ------------------------------------------------------------------------------------------------------------------ */ -------------------------------------------------------------------------------- /Rewrite/deob/structures.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | typedef enum InsnType { 13 | X86_DST_REG_SRC_REG = 0, 14 | X86_DST_REG_SRC_MEM, 15 | X86_DST_REG_SRC_IMM, 16 | X86_DST_MEM_SRC_REG, 17 | X86_DST_MEM_SRC_IMM, 18 | X86_DST_REG, 19 | X86_DST_MEM, 20 | X86_DST_IMM, 21 | X86_NO_OP 22 | } InsnType; 23 | 24 | typedef enum RegPosition { 25 | REG_FIRST = 0, 26 | REG_SECOND, 27 | REG_THIRD, 28 | REG_FOURTH 29 | } RegPosition; 30 | 31 | typedef struct Instruction { 32 | cs_insn *insn; //pointer to the Capstone structure cs_insn 33 | bool invalid; //it indicates if the instruction is a fake one (e.g. mov eax, eflags) 34 | } Instruction; 35 | 36 | typedef struct MemoryLocation { 37 | uint8_t base; 38 | uint8_t index; 39 | uint32_t scale; 40 | uint32_t disp; 41 | } MemoryLocation; 42 | 43 | typedef struct MemoryValue { 44 | uint64_t address; 45 | uint64_t value; 46 | uint32_t size; 47 | } MemoryValue; 48 | 49 | typedef struct Registers { 50 | uint64_t rax; 51 | uint64_t rbx; 52 | uint64_t rcx; 53 | uint64_t rdx; 54 | uint64_t rbp; 55 | uint64_t rsp; 56 | uint64_t rsi; 57 | uint64_t rdi; 58 | uint64_t r8; 59 | uint64_t r9; 60 | uint64_t r10; 61 | uint64_t r11; 62 | uint64_t r12; 63 | uint64_t r13; 64 | uint64_t r14; 65 | uint64_t r15; 66 | uint64_t rip; 67 | } Registers; 68 | 69 | typedef struct InsnMatch { 70 | InsnType type; //indicates the type of instruction to match 71 | uint32_t id; //it is the instruction opcode, refer to x86_insn from Capstone 72 | uint8_t dst_reg; //destination register 73 | uint8_t src_reg; //source register 74 | //uint8_t third_reg; //third register -> unused for now 75 | //uint8_t fourth_reg; //fourth register -> unused for now 76 | uint64_t src_imm; //source immediate 77 | MemoryLocation mem; //memory location structure: base, index, scale, displacement 78 | bool specific_match; //used to know if we need a specific match or a general (only the 'type' is checked) 79 | bool wildcard_dst_reg; //wildcard flag for dst_reg, when set dst_reg is ignored 80 | bool wildcard_src_reg; //wildcard flag for src_reg, when set src_reg is ignored 81 | bool wildcard_mem; //wildcard flag for mem, when set mem is ignored 82 | bool wildcard_imm; //wildcard flag for imm, when set imm is ignored 83 | } InsnMatch; 84 | 85 | typedef struct InsnAccess { 86 | uint8_t access_type; //determine the access type, using the Capstone ones: CS_AC_READ, CS_AC_WRITE & (CS_AC_READ|CS_AC_WRITE) 87 | uint8_t op_type; //determine the type of the operand to check, using the Capstone ones: X86_OP_REG, X86_OP_MEM & X86_OP_IMM 88 | uint8_t reg; //the register to trace 89 | MemoryLocation mem; //the memory location to trace 90 | bool same_reg; //used to know if we want an equality check of the register, or a is_same_register_type is ok 91 | } InsnAccess; 92 | -------------------------------------------------------------------------------- /Rewrite/deob/tests.h: -------------------------------------------------------------------------------- 1 | //x86 2 | #define MODE CS_MODE_32 3 | 4 | //SmilingWolf new mega test #1 x32 5 | #define CODE "\x60\x60\x8B\xF6\x8B\xD2\x61\x8B\xD2\x8B\xF6\x61\x50\x52\x60\x60\x61\x61\x60\x8B\xD2\x60\x61\x61\x5A\x58\x9C\x52\x3E\xC7\x04\x24\x3C\x67\x2F\x06\x3E\x89\x0C\x24\x3E\xC7\x04\x24\x35\x00\x00\x00\x50\x3E\xC7\x04\x24\x76\x9C\x77\x7E\x3E\x81\x24\x24\x5B\x1C\xFF\x7D\x3E\xC1\x24\x24\x02\x3E\x81\x04\x24\x00\x52\xCD\x6C\x3E\x81\x04\x24\x40\x62\xB5\x20\x3E\x81\x04\x24\x6D\x86\xB6\x80\x50\x52\x3E\xC7\x04\x24\xB9\xE1\xE9\x2E\x3E\x89\x1C\x24\x3E\x8B\x44\x24\x10\x3E\x8B\x5C\x24\x08\x3E\x89\x44\x24\x08\x3E\x89\x5C\x24\x10\x5B\x58\x52\x50\x52\x60\x61\x8B\xFF\x8B\xD2\x5A\x58\x50\x52\x60\x61\x5A\x58\x5A\x52\x3E\xC7\x04\x24\x35\xE8\xC3\x3B\x51\xB9\xFD\x3E\xCA\xF7\x3E\x29\x4C\x24\x04\x3E\xFF\x34\x24\x59\x83\xC4\x04\x50\xB8\x91\xB7\xFD\x7E\x3E\x21\x44\x24\x04\x58\x50\x3E\x89\x3C\x24\xBF\x2E\x3D\xF4\x57\x3E\x09\x7C\x24\x04\x5F\x55\xBD\x61\xCB\xFF\x7E\x3E\x21\x6C\x24\x04\x3E\x8B\x2C\x24\x83\xC4\x04\x3E\x81\x24\x24\xEA\x9B\xCB\x0A\x50\x3E\xFF\x74\x24\x04\x58\x3E\x8F\x04\x24\x95\x55\x51\x5D\x59\xF7\xD1\x55\x51\x5D\x59\x33\xC5\x33\xE8\x33\xC5\x3E\x31\x04\x24\x3E\x33\x04\x24\x3E\x31\x04\x24\x3E\x81\x04\x24\xD1\x56\x49\x6B\x3E\x89\x04\x24\x51\x3E\xC7\x04\x24\x1A\x63\xC9\x7B\x3E\x81\x2C\x24\xAD\x90\x4B\x00\x3E\x83\x04\x24\xFF\x3E\xFF\x0C\x24\x57\xBF\x96\x7B\xB2\x00\x3E\x31\x7C\x24\x04\x3E\xFF\x34\x24\x5F\x56\x8B\xF4\x83\xC6\x04\x83\xC6\x04\x3E\x87\x34\x24\x5C\x3E\x81\x24\x24\xC3\x64\x6F\x7E\x51\x3E\xC7\x04\x24\xE1\x26\x1C\x6E\x3E\x89\x0C\x24\x56\xBE\xB0\x05\x7E\x3B\x8B\xCE\x5E\x3E\x81\x6C\x24\x04\x38\x85\xFF\x6F\x3E\x81\x6C\x24\x04\xFE\xB8\xF1\x6F\x53\xBB\x78\x9F\xF5\x3F\x3E\x29\x5C\x24\x08\x3E\x8B\x1C\x24\x83\xC4\x04\x3E\x01\x4C\x24\x04\x3E\x81\x44\x24\x04\x78\x9F\xF5\x3F\x50\xB8\xFE\xB8\xF1\x6F\x3E\x01\x44\x24\x08\x58\x3E\x81\x44\x24\x04\x38\x85\xFF\x6F\x59\x3E\x81\x04\x24\x1C\xF3\xCC\x72\x3E\x89\x0C\x24\x68\xB2\x0E\xC7\x44\x3E\x89\x14\x24\x54\x3E\xFF\x34\x24\x5A\x53\x3E\x89\x0C\x24\x68\xC2\x55\x60\x63\x3E\x89\x24\x24\x3E\x83\x04\x24\x04\x3E\x8B\x0C\x24\x83\xC4\x04\x83\xC1\x04\x52\x50\x68\x35\xB6\x0F\x0B\x58\x55\x53\xBB\xE3\xFD\x3C\x30\x8B\xEB\x5B\x33\xC5\x5D\x56\x8B\xF0\x8B\xD6\x5E\x58\x81\xC2\x2E\xB4\xCC\xC4\x03\xCA\x3E\x8B\x14\x24\x83\xC4\x04\x3E\x87\x0C\x24\x5C\x83\xC2\x04\x83\xEA\x04\x3E\x87\x14\x24\x3E\x8B\x24\x24\x3E\x89\x3C\x24\x3E\x89\x14\x24\x51\x3E\x89\x3C\x24\x54\x3E\xFF\x34\x24\x5F\x83\xC4\x04\x56\xBE\x04\x00\x00\x00\x55\xBD\xBF\x2D\xEC\x3B\x45\x4D\x81\xC5\x16\xB0\x0B\xDE\x03\xFD\x5D\x03\xFE\x81\xEF\xD5\xDD\xF7\x19\x5E\x51\x53\x3E\xC7\x04\x24\x7B\xA1\x7A\x03\x3E\x89\x14\x24\x56\xBE\x16\xFE\xEF\x6D\x4E\x51\xB9\x69\x07\x53\x67\x81\xC9\xD8\xA0\x7F\x7F\x81\xF1\xB7\x59\xFF\x0F\xC1\xE9\x08\xC1\xE9\x02\x81\xF1\xC4\xEE\x01\x4D\x2B\xF1\x59\x81\xF6\x89\x81\x76\x37\xC1\xE6\x03\xC1\xE6\x03\x81\xF6\xC4\xA4\x2B\xE9\x8B\xD6\x5E\x52\x59\x5A\x2B\xF9\x3E\xFF\x34\x24\x59\x50\x8B\xC4\x83\xC0\x04\x83\xC0\x04\x3E\x33\x04\x24\x3E\x31\x04\x24\x3E\x33\x04\x24\x5C\x3E\x87\x3C\x24\x5C\x3E\x89\x1C\x24\x57\x3E\x89\x1C\x24\x52\x3E\x89\x04\x24\x3E\xC7\x04\x24\x06\xB2\x6C\x53\x3E\x89\x3C\x24\x68\xD3\xCF\xFF\x5F\x3E\x8B\x3C\x24\x83\xC4\x04\x3E\x89\x7C\x24\x04\x3E\x8B\x3C\x24\x53\x3E\x89\x0C\x24\x8B\xCC\x83\xC1\x04\x68\xB2\x6D\xD6\x17\x3E\x89\x2C\x24\x50\x68\x13\x06\xF7\x76\x58\x48\x35\x16\x06\xF7\x76\x8B\xE8\x58\x03\xCD\x3E\x8B\x2C\x24\x83\xC4\x04\x3E\x87\x0C\x24\x3E\x8B\x24\x24\x3E\x81\x04\x24\xD1\xFB\xBC\xE9\x3E\x89\x14\x24\x3E\x89\x2C\x24\x3E\x89\x1C\x24\x51\x3E\x89\x1C\x24\x3E\x89\x3C\x24\x3E\x89\x1C\x24\x3E\x89\x04\x24\x3E\xC7\x04\x24\xE4\x81\xFF\x73\x3E\xF7\x14\x24\x3E\xFF\x04\x24\x52\xBA\x3A\xDC\x7E\x5F\x3E\x31\x54\x24\x04\x3E\x8B\x14\x24\x83\xC4\x04\x3E\xC1\x24\x24\x03\x50\x3E\x89\x34\x24\x3E\x89\x2C\x24\x52\xBA\x9C\xB8\xFF\x0C\x51\xB9\xCF\x92\xFF\x30\x8B\xE9\x59\x81\xC5\x1F\x7D\xF1\x7A\x03\xEA\x81\xED\x1F\x7D\xF1\x7A\x3E\x8B\x14\x24\x83\xC4\x04\x3E\x21\x6C\x24\x04\x5D\x3E\xFF\x04\x24\x51\x3E\x89\x04\x24\x3E\x89\x0C\x24\xB9\x95\x0C\x42\xF3\x3E\x29\x4C\x24\x04\x59\x3E\x89\x2C\x24\x52\x52\x3E\x89\x24\x24\x3E\x83\x04\x24\x04\x3E\xFF\x34\x24\x5A\x83\xEC\x04\x3E\x89\x04\x24\x8B\xC4\x51\xB9\x04\x00\x00\x00\x03\xC1\x59\x83\xC0\x04\x3E\x33\x04\x24\x3E\x31\x04\x24\x3E\x33\x04\x24\x3E\x8B\x24\x24\x83\xC2\x04\x50\xB8\x04\x00\x00\x00\x2B\xD0\x58\x3E\x87\x14\x24\x3E\x8B\x24\x24\x3E\x89\x14\x24\x8B\xD4\x83\xC2\x04\x83\xEA\x04\x3E\x33\x14\x24\x3E\x31\x14\x24\x3E\x33\x14\x24\x3E\x8B\x24\x24\x3E\x89\x04\x24\x3E\x89\x2C\x24\x3E\x89\x34\x24\x83\xEC\x04\x3E\x89\x14\x24\x3E\xC7\x04\x24\xA2\x22\x76\x6D\x3E\xF7\x14\x24\x3E\xC1\x2C\x24\x05\x57\x3E\xFF\x74\x24\x04\x5F\x3E\x8F\x04\x24\x4F\x3E\x31\x3C\x24\x3E\x33\x3C\x24\x3E\x31\x3C\x24\x3E\xD1\x2C\x24\x57\x50\xB8\x95\x64\xFF\x3F\x8B\xF8\x58\x3E\x81\x6C\x24\x04\x00\x1B\x3F\x36\x3E\x01\x7C\x24\x04\x3E\x81\x44\x24\x04\x00\x1B\x3F\x36\x3E\x8B\x3C\x24\x83\xC4\x04\x51\x54\x59\x83\xC1\x04\x55\xBD\x04\x00\x00\x00\x81\xE9\x88\xA9\x44\x1B\x2B\xCD\x81\xC1\x88\xA9\x44\x1B\x5D\x3E\x87\x0C\x24\x3E\x8B\x24\x24\x3E\x89\x04\x24\xB8\xC6\x35\x03\xD3\x3E\x29\x44\x24\x04\x58\x3E\x89\x2C\x24\x3E\x89\x34\x24\x3E\x89\x3C\x24" 6 | //#define CODE "\xFF\x34\x24\xFF\x34\x24\x8B\x0C\x24\x83\xC4\x04\x81\xC4\x04\x00\x00\x00\x51\x57\x54\x8F\x04\x24\x81\x04\x24\x04\x00\x00\x00\x59\x81\xC1\x04\x00\x00\x00\x81\xEC\x04\x00\x00\x00\x89\x04\x24\x52\x51\xB9\xF1\x0F\xF8\x49\x68\x3A\x16\x65\xCD\x5A\x01\xCA\x59\x81\xF2\x4D\x10\x79\x3F\xF7\xD2\x81\xEA\xFD\xEF\xDF\x77\x68\x33\xC5\xDA\x3F\x89\x0C\x24\xB9\xA6\xC8\xFF\x6E\x09\xCA\x8B\x0C\x24\x81\xC4\x04\x00\x00\x00\x57\xBF\x46\x26\x00\x80\x01\xFA\x5F\x89\xD0\x8B\x14\x24\x83\xC4\x04\x01\xC1\x8B\x04\x24\x83\xC4\x04\x87\x0C\x24\x5C\x68\xE3\x01\x67\x0A\x89\x2C\x24\x51\xB9\x3E\x04\x00\x00\x89\xCD\x59\x81\xC1\xC2\x6F\xD3\x7B\x56\xBE\x7D\x11\xFF\x3D\x81\xC6\x9D\xD4\xFD\xF8\x29\xF1\x5E\x81\xE9\x1C\x5B\x8C\x5F\x29\xE9\x52\xBA\x1C\x5B\x8C\x5F\x01\xD1\xFF\x34\x24\x5A\x83\xC4\x04\x81\xC1\x1A\xE6\xFC\x36\x81\xE9\xC2\x6F\xD3\x7B\xFF\x34\x24\x8B\x2C\x24\x83\xC4\x04\x57\x54\x5F\x81\xC7\x04\x00\x00\x00\x52\x57\xBF\x24\x2F\xF7\x5D\x89\xFA\x5F\x52\x89\x0C\x24\xB9\xB5\xB1\x7C\x55\xF7\xD9\xC1\xE1\x08\x81\xF1\x84\x5C\x7F\x65\x81\xF1\xE4\xFA\xFB\x3F\x81\xC1\xC0\x41\x2C\x84\x31\xCA\x59\x01\xD7\x8B\x14\x24\x81\xC4\x04\x00\x00\x00\x87\x3C\x24\x5C\x55\x53\xBB\x48\x50\xDF\x4F\x81\xEB\x25\xC8\x52\x7D\x81\xEB\x0A\x7D\x3E\x6F\xC1\xE3\x07\xF7\xDB\x43\x81\xEB\x65\x5C\x91\x09\x89\xDD\x5B\x83\xEC\x04\x89\x34\x24\x68\x28\x9D\xC9\x3F\x89\x0C\x24\xB9\xF6\x77\xF7\x7F\x89\xCE\x59\x55\x89\x0C\x24\xB9\x64\x2E\xBF\x7F\x81\xEE\xF9\x57\x8D\x1B\x81\xC6\xEB\xEC\x35\x7F\x01\xCE\x81\xEE\xEB\xEC\x35\x7F\x81\xC6\xF9\x57\x8D\x1B\x59\x51\xB9\x49\xE9\xD4\x79\x01\xCE\x59\xC1\xEE\x02\x81\xEE\xFF\xFF\xFF\xFF\xF7\xDE\x50\xB8\x99\x5C\xA2\x9F\x31\xC6\x58\x31\xF5\x8B\x34\x24\x83\xC4\x04\xF7\xDD\x4D\x57\x89\x34\x24\xBE\x81\xA7\xBF\x6D\x81\xEE\x01\x00\x00\x00\x81\xEE\xEA\xB3\xFD\x0D\x56\xFF\x04\x24\x5E\x81\xC6\x35\xFD\x97\xD1\x81\xED\xB5\x28\xBB\x1D\x01\xF5\x81\xC5\xB5\x28\xBB\x1D\x5E\x81\xE9\xCD\x8A\xBD\x5F\x29\xE9\x81\xC1\xCD\x8A\xBD\x5F\x5D\x52\x89\x04\x24\x68\x44\xC4\xE2\x79\x89\x3C\x24\xC7\x04\x24\x6F\x28\xFF\x5F\xFF\x04\x24\xFF\x0C\x24\x81\x2C\x24\xF3\xCD\xA7\xF8\x8B\x04\x24\x83\xC4\x04\xC1\xE0\x07\x57\xBF\xC4\xA0\x93\x7F\x81\xC7\x81\x65\x9A\x7F\xC1\xE7\x02\x56\xBE\x01\x00\x00\x00\x29\xF7\x5E\x81\xF7\x13\x3E\x14\x57\x31\xF8\x5F\x55\x89\x04\x24\x81\x04\x24\x55\x9B\x6E\x7F\x8B\x2C\x24\x83\xC4\x04\x53\x55\x56\xC7\x04\x24\x80\xA1\x7C\x5F\x5D\xC1\xE5\x05\x52\xBA\x96\x1E\xFF\x77\x81\xF2\xC3\xB5\x05\xE7\x31\xD5\x5A\x89\xEB\x8B\x2C\x24\x51\x89\xE1\x81\xC1\x04\x00\x00\x00\x83\xC1\x04\x87\x0C\x24\x5C\x29\xDD\x8B\x1C\x24\x83\xC4\x04\x8B\x04\x24\x81\xC4\x04\x00\x00\x00\x57\x68\xBA\x6F\xFF\x7D\x8B\x3C\x24\x81\xC4\x04\x00\x00\x00\xC1\xEF\x08\x81\xEC\x04\x00\x00\x00\x89\x34\x24\xBE\xE6\xBA\x81\x5D\x53\xBB\xCF\xD2\xBF\x6F\x01\xDF\x5B\x01\xF7\x50\xB8\xCF\xD2\xBF\x6F\x29\xC7\x58\x5E\x81\xC5\xF3\x84\x7F\x7E\x01\xFD\x81\xED\xF3\x84\x7F\x7E\x5F\x81\xED\x1D\xA8\xFE\x4C\x81\xC5\x50\xD1\xE1\x5F\x01\xCD\x56\xBE\x50\xD1\xE1\x5F\x81\xC5\x82\xA1\xFF\x7A\x29\xF5\x81\xED\x82\xA1\xFF\x7A\x5E\x81\xC5\x1D\xA8\xFE\x4C\x51\x57\xBF\xCA\x62\xDF\x7F\x81\xCF\x00\x1D\xF6\x7B\xC1\xE7\x08\xC1\xEF\x03\x81\xCF\x32\x5C\x3D\x6E\x81\xCF\x0D\x21\x7B\x4B\x81\xC7\xD6\xBC\xFF\xDD\x89\xF9\x5F\x81\xED\xB8\x03\xBF\x7E\x29\xCD\x81\xC5\xB8\x03\xBF\x7E\x8B\x0C\x24\x68\x01\x76\x12\x75\x89\x0C\x24\x89\xE1\x81\xC1\x04\x00\x00\x00\x83\xC1\x04\x87\x0C\x24\x5C\x83\xEC\x04\x89\x3C\x24\x89\xE7\x55\x89\xE5\x81\xC5\x04\x00\x00\x00\x83\xED\x04\x87\x2C\x24\x5C\x89\x34\x24\x89\x1C\x24\x55\xBD\x2F\x3A\x6F\x6A\x89\xEB\x5D\x56\xBE\x17\x30\x3F\x2E\x01\xF3\x8B\x34\x24\x83\xC4\x04\x83\xEB\xFF\x81\xC3\xBD\x95\x51\x67\x81\xEF\x67\xA2\x7E\x4D\x01\xDF\x53\xBB\xD4\x89\x3F\x7E\x83\xC3\xFF\x81\xCB\xE3\xC9\x7B\x4D\x4B\x4B\x81\xF3\x96\x6B\x01\x32\x01\xDF\x5B\x8B\x1C\x24\x81\xC4\x04\x00\x00\x00\x50\xB8\x04\x00\x00\x00\x29\xC7\x58\x51\x89\x3C\x24\xFF\x74\x24\x04\x8B\x3C\x24\x81\xC4\x04\x00\x00\x00\x8F\x04\x24\x8B\x24\x24\x89\x0C\x24\x55\xBD\xBF\x0D\x26\x37\x81\xCD\x9E\x5C\xDE\x17\x81\xF5\xCF\x5D\xED\x2C\x81\xED\xFF\xFF\xFF\xFF\x51\xB9\xCE\xBF\xFF\x7F\x01\xCD\x8B\x0C\x24\x53\x89\xE3\x81\xC3\x04\x00\x00\x00\x83\xC3\x04\x87\x1C\x24\x5C\x83\xEC\x04\x89\x14\x24\xBA\x3F\x80\xFD\x7B\x09\xD5\xFF\x34\x24\x8B\x14\x24\x81\xC4\x04\x00\x00\x00\x52\x89\x2C\x24\x54\x5D\x81\xC5\x04\x00\x00\x00\x81\xC5\x04\x00\x00\x00\x87\x2C\x24\x8B\x24\x24\x51\xB9\xC2\x3F\x00\x04\x81\xC5\xF4\x8F\xFF\x7D\x01\xCD\x81\xED\xF4\x8F\xFF\x7D\x8B\x0C\x24\x81\xC4\x04\x00\x00\x00\x56\x89\x2C\x24\x59\x8B\x2C\x24\x81\xC4\x04\x00\x00\x00\x68\xC6\x7E\x1D\x4A\x89\x1C\x24\x89\xE3\x81\xC3\x04\x00\x00\x00\x81\xEB\x04\x00\x00\x00\x87\x1C\x24\x8B\x24\x24\x89\x3C\x24\x56\x68\x57\x8F\x6C\x3D\x8B\x34\x24\x83\xC4\x04\xC1\xE6\x02\xF7\xD6\xC1\xE6\x03\x81\xC6\x3B\xEB\x91\xAD\x89\xF7\xFF\x34\x24\xFF\x34\x24\x5E\x53\x54\x5B\x51\xB9\x04\x00\x00\x00\x01\xCB\x59\x81\xC3\x04\x00\x00\x00\x87\x1C\x24\x5C\x68\x45\x73\x55\x7C\x89\x0C\x24\x89\xE1\x81\xC1\x04\x00\x00\x00\x83\xC1\x04\x33\x0C\x24\x31\x0C\x24\x33\x0C\x24\x8B\x24\x24\x55\x89\xFD\x89\xEB\x5D\x8B\x3C\x24\x81\xC4\x04\x00\x00\x00\x31\xC0" 7 | //#define CODE "\xFF\x34\x24\x8B\x0C\x24\x81\xC4\x04\x00\x00\x00\x81\xEC\x04\x00\x00\x00\x89\x04\x24\x89\x34\x24\x89\xE6\x68\x55\xB9\xAC\x24\x89\x2C\x24\x52\xBA\xAE\x2D\x7D\x5F\x89\xD5\x5A\xF7\xD5\x50\xC7\x04\x24\x81\xD5\xA1\x48\x89\x3C\x24\x89\x34\x24\xBE\xF2\x3B\xFF\x6F\x09\xF5\x8B\x34\x24\x81\xC4\x04\x00\x00\x00\xF7\xD5\x81\xF5\xE2\xA5\xDF\x7D\x53\xBB\x4D\x68\xED\x4F\x81\xF3\xD4\x36\xF7\x71\x43\x43\xC1\xEB\x01\x81\xC3\xC9\x2E\x13\x73\x01\xDD\x5B\x81\xC6\x96\xE8\xF8\x03\x81\xC6\x15\x52\xBD\x75\x01\xEE\x81\xEE\x15\x52\xBD\x75\x51\xB9\x96\xE8\xF8\x03\x29\xCE\x59\x8B\x2C\x24\x81\xC4\x04\x00\x00\x00\x81\xC6\x04\x00\x00\x00\x56\xFF\x74\x24\x04\x5E\x8F\x04\x24\x5C\x51\x54\x59\x50\xB8\x04\x00\x00\x00\x01\xC1\x58\x55\xBD\x04\x00\x00\x00\x81\xE9\x5D\xB0\xF9\x29\x29\xE9\x50\xB8\x5D\xB0\xF9\x29\x01\xC1\x58\x5D\x87\x0C\x24\x8B\x24\x24\x89\x14\x24\x53\xBB\xD2\x64\x0D\x27\x53\x5A\x5B\x51\xB9\xF8\xF4\xCF\x7C\xF7\xD1\x87\xE9\x45\x87\xE9\x81\xE9\x48\x89\x3F\x7D\x81\xE9\xFC\xF4\xA3\x5B\x81\xEC\x04\x00\x00\x00\x89\x0C\x24\xF7\x1C\x24\x59\x81\xC1\x1D\x28\x3F\x83\x01\xCA\x59\x89\xD3\x8B\x14\x24\x56\x54\x8B\x34\x24\x83\xC4\x04\x81\xC6\x04\x00\x00\x00\x81\xC6\x04\x00\x00\x00\x33\x34\x24\x31\x34\x24\x33\x34\x24\x5C\x50\x83\xEC\x04\x89\x0C\x24\x55\x57\x68\x00\xB2\xBE\x6E\x5F\x81\xEF\xCD\x3B\x3F\x7F\x81\xF7\x1E\xA1\x8C\x98\x89\xFD\x5F\x50\xB8\xBA\x27\xFB\x74\x29\x44\x24\x08\x58\x01\x6C\x24\x04\x81\x44\x24\x04\xBA\x27\xFB\x74\xFF\x34\x24\xFF\x34\x24\x5D\x81\xC4\x04\x00\x00\x00\x81\xC4\x04\x00\x00\x00\x58\x56\x89\x3C\x24\x89\x14\x24\xBA\xA8\x83\xFD\x14\x81\xE2\x22\xD6\x1D\x7D\x81\xEA\xF3\xAA\x29\x9C\x29\xD0\x5A\x50\x81\x04\x24\xF4\x99\x73\x7E\x8F\x44\x1D\x00\x51\x55\xBD\x85\x1B\xDF\x41\x89\xE9\x5D\x81\xE9\x96\x3E\x8F\x7B\x57\xBF\xDB\xC3\x8D\x6B\xF7\xD7\x81\xF7\xA3\x94\x79\x77\xF7\xDF\x81\xF7\xAE\xD8\x28\x5B\x21\xF9\x5F\xC1\xE9\x02\x49\xF7\xD1\x81\xF1\x3B\x45\x1F\x90\x29\x4C\x1D\x00\x59\xFF\x34\x24\x58\x83\xC4\x04\x56\xBE\x61\x2E\xFE\x3D\x81\xEE\x9A\x13\xEB\x72\x50\xB8\xF5\x9E\x77\x6B\x25\x97\x34\xBC\x7F\x81\xEC\x04\x00\x00\x00\x89\x3C\x24\xBF\x02\xD2\xF5\x5F\xC1\xE7\x04\x81\xF7\xA6\xAA\x8F\x2F\x4F\x4F\xC1\xE7\x08\x50\xB8\xA8\xC1\x7A\x79\xC1\xE0\x08\x48\x05\x7B\xBA\xFD\x37\xF7\xD0\xC1\xE8\x02\x2D\x6F\xA2\x74\x6B\x01\xC7\x8B\x04\x24\x81\xC4\x04\x00\x00\x00\x31\xF8\x5F\x53\xBB\x5C\x6D\x4F\x5F\x81\xCB\x58\x4C\x67\x0F\xC1\xEB\x08\x52\xBA\x00\xC0\xFB\x79\x09\xD3\x8B\x14\x24\x83\xC4\x04\x81\xEB\xB0\x64\xDD\x57\x81\xF3\xE5\x81\xF1\x83\x05\x42\xF2\xFF\x6C\x29\xD8\x2D\x42\xF2\xFF\x6C\x5B\x31\xC6\x58\x4E\x50\x57\x56\x68\x32\x45\xEB\x39\x8B\x34\x24\x81\xC4\x04\x00\x00\x00\x81\xE6\x51\x9A\xFF\x6F\x46\x81\xC6\x45\x0B\x81\x7A\x89\xF7\x8B\x34\x24\x83\xC4\x04\x89\xF8\x5F\x31\xC6\x8B\x04\x24\x83\xC4\x04\x89\xF3\x5E\x53\xC7\x04\x24\xA0\x09\x4B\x06\x89\x0C\x24\x68\x00\x00\x40\x00\x8B\x0C\x24\x81\xC4\x04\x00\x00\x00\x51\x89\xE1\x50\xB8\x04\x00\x00\x00\x01\xC1\x8B\x04\x24\x81\xC4\x04\x00\x00\x00\x55\xBD\x04\x00\x00\x00\x81\xEC\x04\x00\x00\x00\x89\x14\x24\xBA\x46\x3F\xF9\x7F\x81\xCA\x32\xF6\xFF\x63\x50\xB8\x42\x74\x20\x62\x31\xC2\x58\x29\xD1\x5A\x29\xE9\x81\xC1\x34\x8B\xDF\x1D\x8B\x2C\x24\x83\xC4\x04\x51\xFF\x74\x24\x04\xFF\x34\x24\x59\x83\xC4\x04\x8F\x04\x24\x5C\x89\x0C\x24\x81\x04\x24\xFA\x14\x7F\x47\x8F\x44\x1D\x00\x81\x6C\x1D\x00\xFA\x14\x7F\x47\x8B\x0C\x24\x83\xC4\x04\x55\xC7\x04\x24\x72\xC1\x4F\x5F\x5B\xF7\xDB\x51\x89\xE1\x81\xC1\x04\x00\x00\x00\x81\xE9\x04\x00\x00\x00\x87\x0C\x24\x5C\x89\x04\x24\x55\xBD\xED\x58\xFF\x7F\x87\xD5\x57\xBF\xF1\xEB\xEF\x6F\x81\xC7\x22\x1A\xD7\x67\x81\xE7\x85\x0E\x3D\x5F\x81\xF7\x00\x10\xEF\x7E\xC1\xE7\x03\x81\xF7\xF7\x4F\xAF\xB0\x01\xFA\x5F\x87\xD5\x81\xCD\x07\x63\xFB\x7B\x50\xB8\x01\x2F\xC6\x37\x81\xC5\xBB\xEE\xFE\x6D\x81\xED\x94\x43\xFF\x77\x29\xC5\x81\xC5\x94\x43\xFF\x77\x81\xED\xBB\xEE\xFE\x6D\x58\xF7\xDD\x81\xE5\x90\xB8\xEF\x76\x81\xED\x50\x07\x10\xD9\x89\xE8\xFF\x34\x24\x5D\x51\x89\xE1\x81\xC1\x04\x00\x00\x00\x83\xC1\x04\x87\x0C\x24\x5C\x68\x00\x00\x00\x00\x29\x04\x24\x58\x52\xBA\x8E\xAB\xAD\x62\x29\xD0\x5A\x29\xC3\x58\x55\xBD\xBB\x92\x14\x61\x29\xEB\x8B\x2C\x24\x83\xC4\x04\xFF\x74\x24\x28\xFF\x34\x24\x58\x52\x68\xCB\x44\x08\x0D\x89\x34\x24\x89\x24\x24\x83\xEC\x04\x89\x14\x24\x89\x04\x24\xB8\x5B\x6F\x5F\x67\x51\xB9\x84\x4C\xAB\x5F\x31\xC8\x59\x52\xBA\xDA\x31\x3B\x7F\x29\xD0\x5A\x52\xBA\x39\xFC\xFF\x7F\x21\xD0\x5A\xC1\xE8\x03\x0D\x68\x96\x79\x1C\x53\xBB\x1E\x22\xBF\x53\x81\xE3\x2A\xED\x90\x62\x81\xF3\x75\xEB\x1F\x3F\x81\xEB\x96\x30\x75\x6A\x81\xF3\x75\xFB\x9A\xF3\x01\xD8\x5B\x01\x44\x24\x04\x8B\x04\x24\x83\xC4\x04\x5A\x81\xC2\x04\x00\x00\x00\x55\xBD\x04\x00\x00\x00\x81\xEA\x5A\xC1\xEB\x2F\x01\xEA\x81\xC2\x5A\xC1\xEB\x2F\x5D\x33\x14\x24\x31\x14\x24\x33\x14\x24\x8B\x24\x24\x2D\x56\x7E\x9F\x6F\x2D\xFA\xFE\xB7\x25\x01\xC8\x68\x9B\x7D\x2D\x4D\x89\x04\x24\x54\x58\x05\x04\x00\x00\x00\x2D\x04\x00\x00\x00\x87\x04\x24\x5C\x89\x3C\x24\x56\x89\x14\x24\xBA\x03\x33\x93\x1A\x52\x52\xBA\x38\x04\xFF\x7F\x31\x54\x24\x04\x5A\x5F\x81\xF7\x38\x04\xFF\x7F\x5A\xC1\xEF\x03\x81\xEF\x9A\xCC\xE3\x7D\x81\xC7\x34\x65\x49\xA0\x2D\xFF\x93\xFF\x7D\x01\xF8\x05\xFF\x93\xFF\x7D\x5F\x81\xEC\x04\x00\x00\x00\x89\x2C\x24\x53\xBB\xD2\x2E\xF7\x6B\x68\x84\x50\x68\x04\x5D\x31\xDD\x5B\x05\x8F\x60\xDF\x7F\x01\xE8\x56\xBE\x8F\x60\xDF\x7F\x29\xF0\x5E\x8B\x2C\x24\x56\x89\xE6\x81\xC6\x04\x00\x00\x00\x83\xC6\x04\x87\x34\x24\x5C\x68\x96\x53\x6B\x6E\x89\x14\x24\x89\xDA\x68\xE4\x02\xB7\x7D\x89\x2C\x24\x51\xB9\x26\xB1\xFB\x6F\x41\x49\x49\x81\xC9\x13\x0B\xED\x68\x81\xF1\xC4\xF1\x62\x17\x51\x81\x2C\x24\xD8\xBF\xEF\x3B\x5D\x57\xBF\xC1\xE6\x0B\x7F\xF7\xDF\xC1\xEF\x08\x81\xE7\x48\x45\x3C\x7B\x4F\xC1\xE7\x06\x81\xF7\x18\xBE\xFE\x3B\x01\xFD\x5F\x59\x81\xF5\xF3\x4A\x9D\x78\x01\xEA\x8B\x2C\x24\x83\xC4\x04\x53\x89\xE3\x81\xC3\x04\x00\x00\x00\x51\xB9\x5F\x2D\xEC\x37\x49\x53\xBB\xA6\xD2\x13\xC8\x01\xD9\x5B\x29\xCB\x59\x87\x1C\x24\x8B\x24\x24\x89\x2C\x24\xBD\x47\x0E\x4F\x7D\x81\xC5\x03\xA0\x3A\x69\x52\xBA\x50\x6F\x76\xF1\x31\xD5\x8B\x14\x24\x81\xC4\x04\x00\x00\x00\x81\xC2\x9E\xBC\xEB\x2F\x01\xEA\x81\xEA\x9E\xBC\xEB\x2F\x5D\x01\xEA\x81\xEA\x1A\xC1\xFF\x17\x53\x89\xC3\x89\x1A\x5B\x5A\x51\x56\xBE\x0D\x32\xDB\x3A\xC1\xE6\x03\x81\xF6\x2E\x6C\x66\xE9\x68\x00\x00\x00\x00\x81\x04\x24\xCC\x9A\xFF\x3F\x29\x34\x24\x81\x2C\x24\xCC\x9A\xFF\x3F\x5E\x31\xCE\x31\xF1\x31\xCE\x41\x87\xCE\xC1\xE6\x05\x83\xEC\x04\x89\x14\x24\x68\x2C\xA2\xFA\x64\x89\x1C\x24\x51\x89\x2C\x24\x68\x03\xB0\x79\x1F\x5D\xC1\xE5\x08\xF7\xD5\xF7\xDD\x56\xBE\x04\x70\xCF\xF2\x01\xF5\x5E\x89\xEB\x5D\x53\x5A\x5B\x81\xC6\x23\x49\xFA\x0F\x01\xD6\x81\xEE\x23\x49\xFA\x0F\x5A\x81\xEE\xEC\x52\x7C\x74\x89\xF1\x5E\x83\xEC\x04\x89\x0C\x24\x52\xBA\xD6\x3C\xFF\x07\x29\x54\x24\x04\x5A\x58\x56\xBE\xD6\x3C\xFF\x07\x01\xF0\x5E\x59\x83\xEC\x04\x89\x04\x24\x89\x34\x24\x54\x5E\x55\x52\xBA\x04\x00\x00\x00\x89\xD5\x5A\x01\xEE\x5D\x55\xBD\x04\x00\x00\x00\x29\xEE\x5D\x33\x34\x24\x31\x34\x24\x33\x34\x24\x8B\x24\x24\x89\x3C\x24\xBF\x00\x33\xEF\x77\x29\xF8\x5F\x05\xBB\x52\x4D\x76\x05\x00\x42\xFB\x7D\x01\xC8\x2D\x00\x42\xFB\x7D\x2D\xBB\x52\x4D\x76\x68\x95\xF9\xFC\x10\x89\x1C\x24\xBB\x75\xDD\xBF\x1E\x81\xC3\x04\x1A\xEA\x7A\x81\xE3\x60\xB4\x77\x7F\x53\x89\x34\x24\xBE\x14\xE0\xBD\x37\x68\xEE\x91\x2F\x73\x89\x3C\x24\xBF\x74\x67\x73\x59\x31\xFE\x5F\x31\xF3\x5E\x01\xD8\x5B\x56\xBE\x93\x8A\x77\x7D\x81\xF6\x7D\xE9\x7F\x7C\x81\xEE\xD8\xA2\x49\x91\x87\xEE\x55\xF7\x14\x24\x8B\x2C\x24\x81\xC4\x04\x00\x00\x00\x31\xEE\x31\xF5\x31\xEE\x53\x53\x89\x04\x24\xB8\xD6\x3E\x41\x90\x89\xC3\xFF\x34\x24\x58\x83\xC4\x04\x31\xDE\x5B\x51\xC7\x04\x24\x15\x29\x1C\x7E\x89\x2C\x24\x68\x13\x3C\xEE\x52\x89\x34\x24\x8B\x2C\x24\x50\x89\xE0\x05\x04\x00\x00\x00\x05\x04\x00\x00\x00\x87\x04\x24\x5C\x89\xEB\x5D\xFF\x34\x24\x5E\x81\xC4\x04\x00\x00\x00\xFF\x74\x1D\x00\xFF\x34\x24\xFF\x34\x24\xFF\x34\x24\x8B\x14\x24\x83\xC4\x04\x83\xC4\x04\x52\x89\xE2\x81\xC2\x04\x00\x00\x00\x81\xEA\x04\x00\x00\x00\x87\x14\x24\x5C\x89\x04\x24\x52\x89\xE2\x81\xC2\x04\x00\x00\x00\x81\xEA\x04\x00\x00\x00\x33\x14\x24\x31\x14\x24\x33\x14\x24\x5C\x89\x24\x24\x83\x04\x24\x04\x58\x51\xB9\x02\x06\xEC\x52\x52\xBA\xBA\x12\xC9\x2C\x81\xE2\x90\x62\x7E\x5A\x81\xEA\xEE\xF9\x88\xA8\x21\xD1\x5A\x81\xF1\x49\x59\xFA\x5F\xC1\xE9\x05\x81\xF1\xCE\xB2\x6A\x00\x01\xC8\x59\x52\xBA\x04\x00\x00\x00\x01\xD0\x5A\x33\x04\x24\x31\x04\x24\x33\x04\x24\x5C\x83\xC4\x04" 8 | 9 | //test1.txt x32 10 | //#define CODE "\x66\x51\x68\xCB\x63\x00\x00\x3E\x89\x1C\x24\x66\xBB\xDB\x12\x66\xF7\xD3\x66\x81\xCB\x0C\x39\x66\x81\xF3\x2C\xFD\x55\x66\x89\xDD\x66\x89\xE9\x5D\x3E\x8B\x1C\x24\x56\x3E\x89\x14\x24\x89\xE2\x83\xC2\x04\x83\xEA\x04\x3E\x87\x14\x24\x3E\x8B\x24\x24\x3E\x89\x04\x24\x89\xE0\x83\xC0\x04\x83\xC0\x04\x3E\x87\x04\x24\x3E\x8B\x24\x24\x66\x81\xE9\x4D\x07\x66\x29\xC1\x66\x81\xC1\x4D\x07\x66\x31\xC8\x66\x31\xC1\x66\x31\xC8\x66\x3E\x8B\x0C\x24\x68\x1C\x30\x00\x00\x3E\x89\x2C\x24\x3E\x89\x34\x24\x89\xE6\x53\xBB\x03\x5D\x1F\x70\x50\xB8\x3B\x2C\x32\x60\xC1\xE0\x03\xF7\xD8\xF7\xD8\x05\x2F\xFB\x8D\x6E\x31\xC3\x58\x81\xEE\x40\x2E\x44\x49\x81\xC6\xB0\x58\xDA\x73\x01\xDE\x81\xEE\xB0\x58\xDA\x73\x81\xC6\x40\x2E\x44\x49\x3E\x8B\x1C\x24\x83\xC4\x04\x68\x50\x23\x00\x00\x3E\x89\x2C\x24\xBD\x02\x00\x00\x00\x81\xC6\xDC\x0D\x49\x5F\x01\xEE\x81\xEE\xDC\x0D\x49\x5F\x5D\x3E\x33\x34\x24\x3E\x31\x34\x24\x3E\x33\x34\x24\x3E\x8B\x24\x24" 11 | 12 | //root new test #1 x32 13 | //#define CODE "\x50\x89\xC8\x05\x00\x00\x00\x00\x01\xD8\x31\x30\x58\x33\x34\x0B\x52\x89\xCA\x81\xC2\x00\x00\x00\x00\x01\xDA\x31\x32\x5A\x56\xF7\x14\x24\x5E\x87\x34\x0B\x56\x68\xFF\x08\x00\x00\x89\x34\x24\x83\xEC\x04\x89\x24\x24\x81\x04\x24\x04\x00\x00\x00\x5E\x81\xC6\x04\x00\x00\x00\x81\xEE\x04\x00\x00\x00\x33\x34\x24\x31\x34\x24\x33\x34\x24\x5C\x89\x2C\x24\xBD\xF0\x04\x0D\x7F\x81\xED\xB4\x1F\x3A\x18\x81\xF5\xC3\x1A\x2D\x99\x53\x51\x89\xE9\x51\x5B\x59\x89\xDE\xFF\x34\x24\x5B\x81\xC4\x04\x00\x00\x00\x5D\x29\x34\x0B\x5E" 14 | 15 | //root new test #2 x32 -> STACK PROBLEMS 16 | //#define CODE "\x66\x68\x59\x22\x66\x89\x04\x24\x66\x51\x66\x8B\x04\x24\x81\xEC\x04\x00\x00\x00\x89\x04\x24\x54\x58\x83\xEC\x04\x89\x3C\x24\xBF\xD4\x7E\xFB\x17\x81\xF7\x57\x5C\x5B\x52\xF7\xD7\x47\x55\xBD\x79\xDD\x5F\xBA\x31\xEF\x5D\x01\xF8\x5F\x2D\x04\x00\x00\x00\x33\x04\x24\x31\x04\x24\x33\x04\x24\x8B\x24\x24\x89\x1C\x24\x54\x5B\x81\xC3\x04\x00\x00\x00\x57\xBF\x02\x00\x00\x00\x01\xFB\x8B\x3C\x24\x83\xC4\x04\x83\xEC\x04\x89\x1C\x24\xFF\x74\x24\x04\x5B\x8F\x04\x24\x8B\x24\x24\x66\x8B\x0C\x24\x83\xC4\x02" 17 | 18 | //root new test #3 x32 19 | //#define CODE "\x52\x89\xE2\x81\xC2\x04\x00\x00\x00\x81\xEA\x04\x00\x00\x00\x87\x14\x24\x5C\x89\x34\x24\x89\x3C\x24\xBF\x32\x36\x51\x68\x4F\x81\xC7\x26\x58\xC3\x7D\x57\x89\x1C\x24\xBB\x00\x00\x00\x00\x52\x89\xE2\x81\xC2\x04\x00\x00\x00\x83\xEA\x04\x87\x14\x24\x5C\x89\x2C\x24\xBD\xC3\x68\x0A\x75\x45\x81\xCD\x07\x7B\x6B\x1D\xF7\xDD\x45\x81\xCD\xE3\x49\x3C\x0D\x81\xED\x3F\xAC\x9A\x89\x81\xEB\xDA\x5A\x89\x54\x01\xEB\x81\xC3\xDA\x5A\x89\x54\x5D\x29\xFB\x81\xEB\xBC\x21\x22\x06\x68\xF5\x62\x00\x00\x89\x1C\x24\x5F\x8B\x1C\x24\x83\xC4\x04\x68\xD2\x4E\x00\x00\x89\x2C\x24\xBD\xC1\x96\x8D\xFE\x31\xEF\x5D\x09\xBA\x8C\x06\x93\x8B\xFF\x34\x24\x5F\x53\x89\xE3\x81\xC3\x04\x00\x00\x00\x81\xC3\x04\x00\x00\x00\x87\x1C\x24\x5C" 20 | 21 | //root new test #4 x32 22 | //#define CODE "\x57\xBF\x1C\x11\xD9\x3F\x31\xDF\x31\xFB\x31\xDF\xF7\xD3\x87\xDF\xC1\xE7\x07\x56\x89\x0C\x24\x89\x2C\x24\x68\x69\x4E\x29\x63\x8B\x2C\x24\x81\xC4\x04\x00\x00\x00\x21\xEF\xFF\x34\x24\x5D\x53\x54\x5B\x81\xC3\x04\x00\x00\x00\x52\x50\xB8\x64\x07\xE5\x7B\xF7\xD8\xF7\xD8\x48\x2D\x14\x1B\x95\x28\x40\x57\x51\xB9\x4C\xEC\x4F\x53\x89\xCF\x59\x29\xF8\x5F\x89\xC2\x58\x01\xD3\x5A\x33\x1C\x24\x31\x1C\x24\x33\x1C\x24\x5C\xC1\xE7\x07\x47\x81\xEF\x35\x6D\x23\x0B\x2D\xD8\x6A\xBF\x1B\x01\xF8\x05\xD8\x6A\xBF\x1B\xFF\x34\x24\x5F\x83\xC4\x04" 23 | 24 | //root new test #5 x32 25 | //#define CODE "\x68\x82\x10\x64\x5A\x8B\x3C\x24\x57\x89\xE7\x52\x89\x1C\x24\x68\xF6\x19\x00\x00\x89\x34\x24\xBE\xBF\x5C\x33\x15\x50\xB8\x5A\x40\x67\x29\x01\xC6\x58\x56\xFF\x0C\x24\x5E\x83\xEE\xFF\x83\xEC\x04\x89\x14\x24\x51\xB9\x05\x35\x1E\x49\xBA\x1F\x35\x29\x0F\x31\xCA\x59\x50\x57\xBF\xB1\x0A\x09\x52\x89\xF8\x5F\xC1\xE0\x07\x83\xE8\xFF\x2D\x0F\xE3\xBD\xFA\x01\xC2\x8B\x04\x24\x83\xC4\x04\x81\xC2\xFF\xFF\xFF\xFF\x81\xC2\x54\x39\x1A\x31\x51\xB9\x22\x75\xE1\x6F\x09\xCA\x59\x81\xF2\x7D\xD9\x4C\xAB\x53\xBB\xED\x0D\x38\x67\x29\xDE\x5B\x29\xD6\x81\xC6\xED\x0D\x38\x67\x5A\x81\xF6\x93\x76\xE5\xF9\x89\xF3\x5E\x81\xC7\x12\x7A\x5E\x5B\x01\xDF\x55\xBD\x12\x7A\x5E\x5B\x81\xEF\xB0\x09\xCD\x35\x29\xEF\x81\xC7\xB0\x09\xCD\x35\x5D\x5B\x81\xC7\x04\x00\x00\x00\x87\x3C\x24\x8B\x24\x24" 26 | 27 | //root new test #6 x32 28 | //#define CODE "\x8B\x04\x24\x51\x89\xE1\x55\xBD\xFF\x0E\xB7\x6C\xF7\xD5\x87\xF5\x87\xDE\xF7\xD3\x87\xDE\x87\xF5\x87\xDD\x83\xC3\xFF\x87\xDD\xF7\xD5\x81\xED\xFD\xF0\x48\x93\x01\xE9\x5D\x56\x89\xE6\x68\xEA\x54\x00\x00\x89\x3C\x24\xBF\xC1\x26\xD5\x0B\x81\xF7\xC5\x26\xD5\x0B\x01\xFE\xFF\x34\x24\x8B\x3C\x24\x83\xC4\x04\x81\xC4\x04\x00\x00\x00\x83\xEE\x04\x87\x34\x24\x5C\x89\x2C\x24\xBD\x77\x2F\xDF\x2E\x81\xCD\x7E\x1A\x72\x1D\x87\xCD\xF7\xD1\x87\xCD\x81\xF5\x48\x0F\xEC\x2E\x68\x7A\x49\x00\x00\x89\x1C\x24\xBB\x3C\x30\x13\x11\x01\xDD\x5B\x01\xE9\x5D\x87\x0C\x24\x8B\x24\x24" 29 | 30 | //root new test #7 x32 31 | //#define CODE "\x68\x6F\x05\x00\x00\x89\x3C\x24\x89\x0C\x24" 32 | 33 | //root new test #8 x32 34 | //#define CODE "\x50\x56\x53\xBB\x8E\x29\x1C\x66\x89\xDE\x5B\x81\xF6\x57\x29\x1C\x66\x68\x2B\x10\x00\x00\x89\x2C\x24\x51\x89\x1C\x24\x52\x50\x89\xF0\x89\xC2\x58\x89\xD3\x5A\x57\x89\xDF\x89\xFD\x5F\x5B\x57\x89\xEF\x89\xF8\x5F\x8B\x2C\x24\x81\xC4\x04\x00\x00\x00\x5E\x68\xB7\x4A\x00\x00\x89\x14\x24\x53\xBB\xB0\x2D\xF9\x31\xBA\x90\xD4\x06\xCE\x81\xC2\xC7\x32\xEA\x1D\x01\xDA\x81\xEA\xC7\x32\xEA\x1D\x5B\x81\xEA\xFF\x34\x2B\x75\x01\xF2\x81\xC2\xFF\x34\x2B\x75\x31\x02\x5A\x8B\x04\x24\x57\x89\xE7\x81\xC7\x04\x00\x00\x00\x81\xC7\x04\x00\x00\x00\x87\x3C\x24\x8B\x24\x24" 35 | 36 | //new random test #1 x32 37 | //#define CODE "\x81\x04\x18\x77\x07\x00\x00\x81\x2C\x18\x77\x07\x00\x00\x81\x04\x19\x66\x06\x00\x00\x81\x04\x19\x11\x01\x00\x00" 38 | 39 | //new random test #2 x32 40 | #define CODE "\xBB\x66\x00\x00\x00\x83\xEB\x77\x74\x13" -------------------------------------------------------------------------------- /t4y.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fvrmatteo/DeobfuscatorTest/aad1ca892150c5dfe0bbbbd6d932ee879fa0ea0d/t4y.7z --------------------------------------------------------------------------------