00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <string.h>
00022
00023 #include "analy_register.h"
00024 #include "analy_x86.h"
00025 #include "htdebug.h"
00026 #include "snprintf.h"
00027 #include "x86dis.h"
00028
00029 AddressX86Flat32::AddressX86Flat32()
00030 {
00031 }
00032
00033 AddressX86Flat32::AddressX86Flat32(dword Addr)
00034 {
00035 addr = Addr;
00036 }
00037
00038 bool AddressX86Flat32::add(int offset)
00039 {
00040
00041 if ((int)offset < 0) {
00042 if (addr+offset > addr) return false;
00043 } else {
00044 if (addr+offset < addr) return false;
00045 }
00046 addr+=offset;
00047 return true;
00048 }
00049
00050 int AddressX86Flat32::byteSize()
00051 {
00052 return 4;
00053 }
00054
00055 int AddressX86Flat32::compareTo(const Object *obj) const
00056 {
00057
00058
00059
00060 assert(object_id() == obj->object_id());
00061 if (addr > ((AddressX86Flat32 *)obj)->addr) return 1;
00062 if (addr < ((AddressX86Flat32 *)obj)->addr) return -1;
00063 return 0;
00064 }
00065
00066 int AddressX86Flat32::compareDelinear(Address *to)
00067 {
00068 assert(object_id() == to->object_id());
00069 dword da = delinearize(addr);
00070 dword db = delinearize(((AddressFlat32 *)to)->addr);
00071 if (da > db) return 1;
00072 if (da < db) return -1;
00073 return 0;
00074 }
00075
00076 bool AddressX86Flat32::difference(int &result, Address *to)
00077 {
00078 if (object_id() == to->object_id()) {
00079 result = addr-((AddressX86Flat32 *)to)->addr;
00080 return true;
00081 } else {
00082 return false;
00083 }
00084 }
00085
00086 Object *AddressX86Flat32::duplicate()
00087 {
00088 return new AddressX86Flat32(addr);
00089 }
00090
00091 void AddressX86Flat32::getFromArray(const byte *array)
00092 {
00093 UNALIGNED_MOVE(addr, *(dword*)array);
00094 }
00095
00096 void AddressX86Flat32::getFromCPUAddress(CPU_ADDR *ca)
00097 {
00098 addr = ca->addr32.offset;
00099 }
00100
00101 int AddressX86Flat32::load(ht_object_stream *s)
00102 {
00103 addr = s->getIntHex(4, NULL);
00104 return s->get_error();
00105 }
00106
00107 OBJECT_ID AddressX86Flat32::object_id() const
00108 {
00109 return ATOM_ADDRESS_X86_FLAT_32;
00110 }
00111
00112 int AddressX86Flat32::parseString(const char *s, int length, Analyser *a)
00113 {
00114 return 0;
00115 }
00116
00117 void AddressX86Flat32::putIntoArray(byte *array)
00118 {
00119 UNALIGNED_MOVE(*(dword*)array, addr);
00120 }
00121
00122 void AddressX86Flat32::putIntoCPUAddress(CPU_ADDR *ca)
00123 {
00124 ca->addr32.offset = addr;
00125 }
00126
00127 void AddressX86Flat32::store(ht_object_stream *s)
00128 {
00129 s->putIntHex(addr, 4, NULL);
00130 }
00131
00132 int AddressX86Flat32::stringify(char *s, int max_length, int format)
00133 {
00134 char *formats[] = {
00135 "%s%x%s",
00136 "%s%8x%s",
00137 "%s%08x%s",
00138 "",
00139 "%s%X%s",
00140 "%s%8X%s",
00141 "%s%08X%s",
00142 "",
00143 };
00144 return ht_snprintf(s, max_length, formats[format&7], (format & ADDRESS_STRING_FORMAT_ADD_0X) ? "0x":"", addr, (format & ADDRESS_STRING_FORMAT_ADD_H) ? "h":"");
00145 }
00146
00147 int AddressX86Flat32::stringSize()
00148 {
00149 return 8;
00150 }
00151
00152
00153 AddressX86_1632::AddressX86_1632()
00154 {
00155 }
00156
00157 AddressX86_1632::AddressX86_1632(word Seg, dword Addr)
00158 {
00159 seg = Seg;
00160 addr = Addr;
00161 }
00162
00163 bool AddressX86_1632::add(int offset)
00164 {
00165
00166 if ((int)offset < 0) {
00167 if (addr+offset > addr) return false;
00168 } else {
00169 if (addr+offset < addr) return false;
00170 }
00171 addr+=offset;
00172 return true;
00173 }
00174
00175 int AddressX86_1632::byteSize()
00176 {
00177 return 6;
00178 }
00179
00180 int AddressX86_1632::compareTo(const Object *obj) const
00181 {
00182 assert(object_id() == obj->object_id());
00183 if (seg > ((AddressX86_1632 *)obj)->seg) return 1;
00184 if (seg < ((AddressX86_1632 *)obj)->seg) return -1;
00185 if (addr > ((AddressX86_1632 *)obj)->addr) return 1;
00186 if (addr < ((AddressX86_1632 *)obj)->addr) return -1;
00187 return 0;
00188 }
00189
00190 int AddressX86_1632::compareDelinear(Address *to)
00191 {
00192 assert(object_id() == to->object_id());
00193 dword s1 = delinearize(seg);
00194 dword s2 = delinearize(((AddressX86_1632 *)to)->seg);
00195 if (s1 > s2) return 1;
00196 if (s1 < s2) return -1;
00197 dword a1 = delinearize(addr);
00198 dword a2 = delinearize(((AddressX86_1632 *)to)->addr);
00199 if (a1 > a2) return 1;
00200 if (a1 < a2) return -1;
00201 return 0;
00202 }
00203
00204 bool AddressX86_1632::difference(int &result, Address *to)
00205 {
00206 if ((object_id() == to->object_id()) && (seg == ((AddressX86_1632 *)to)->seg)) {
00207 result = addr-((AddressX86_1632 *)to)->addr;
00208 return true;
00209 } else {
00210 return false;
00211 }
00212 }
00213
00214 Object *AddressX86_1632::duplicate()
00215 {
00216 return new AddressX86_1632(seg, addr);
00217 }
00218
00219 void AddressX86_1632::getFromArray(const byte *array)
00220 {
00221 UNALIGNED_MOVE(addr, *(dword*)array);
00222 UNALIGNED_MOVE(seg, *(word*)(array+sizeof addr));
00223 }
00224
00225 void AddressX86_1632::getFromCPUAddress(CPU_ADDR *ca)
00226 {
00227 seg = ca->addr32.seg;
00228 addr = ca->addr32.offset;
00229 }
00230
00231 int AddressX86_1632::load(ht_object_stream *s)
00232 {
00233 seg = s->getIntHex(2, NULL);
00234 addr = s->getIntHex(4, NULL);
00235 return s->get_error();
00236 }
00237
00238 OBJECT_ID AddressX86_1632::object_id() const
00239 {
00240 return ATOM_ADDRESS_X86_1632;
00241 }
00242
00243 int AddressX86_1632::parseString(const char *s, int length, Analyser *a)
00244 {
00245 return 0;
00246 }
00247
00248 void AddressX86_1632::putIntoArray(byte *array)
00249 {
00250 UNALIGNED_MOVE(*(dword*)array, addr);
00251 UNALIGNED_MOVE(*(word*)(array+sizeof addr), seg);
00252 }
00253
00254 void AddressX86_1632::putIntoCPUAddress(CPU_ADDR *ca)
00255 {
00256 ca->addr32.seg = seg;
00257 ca->addr32.offset = addr;
00258 }
00259
00260 void AddressX86_1632::store(ht_object_stream *s)
00261 {
00262 s->putIntHex(seg, 2, NULL);
00263 s->putIntHex(addr, 4, NULL);
00264 }
00265
00266 int AddressX86_1632::stringify(char *s, int max_length, int format)
00267 {
00268 char *formats[] = {
00269 "%s%x%s:%s%x%s",
00270 "%s%4x%s:%s%08x%s",
00271 "%s%04x%s:%s%08x%s",
00272 "",
00273 "%s%X%s:%s%X%s",
00274 "%s%4X%s:%s%08X%s",
00275 "%s%04X%s:%s%08X%s",
00276 "",
00277 };
00278 return ht_snprintf(s, max_length, formats[format&7],
00279 (format & ADDRESS_STRING_FORMAT_ADD_0X) ? "0x":"", seg, (format & ADDRESS_STRING_FORMAT_ADD_H) ? "h":"",
00280 (format & ADDRESS_STRING_FORMAT_ADD_0X) ? "0x":"", addr, (format & ADDRESS_STRING_FORMAT_ADD_H) ? "h":"");
00281 }
00282
00283 int AddressX86_1632::stringSize()
00284 {
00285 return 14;
00286 }
00287
00288
00289
00290
00291 AddressX86_1616::AddressX86_1616()
00292 {
00293 }
00294
00295 AddressX86_1616::AddressX86_1616(word Seg, word Addr)
00296 {
00297 seg = Seg;
00298 addr = Addr;
00299 }
00300
00301 bool AddressX86_1616::add(int offset)
00302 {
00303
00304 if ((int)offset < 0) {
00305 if (addr+offset > addr) return false;
00306 } else {
00307 if (addr+offset < addr) return false;
00308 }
00309 addr+=offset;
00310 return true;
00311 }
00312
00313 int AddressX86_1616::byteSize()
00314 {
00315 return 4;
00316 }
00317
00318 int AddressX86_1616::compareTo(const Object *obj) const
00319 {
00320 assert(object_id() == obj->object_id());
00321 if (seg > ((AddressX86_1616 *)obj)->seg) return 1;
00322 if (seg < ((AddressX86_1616 *)obj)->seg) return -1;
00323 if (addr > ((AddressX86_1616 *)obj)->addr) return 1;
00324 if (addr < ((AddressX86_1616 *)obj)->addr) return -1;
00325 return 0;
00326 }
00327
00328 int AddressX86_1616::compareDelinear(Address *to)
00329 {
00330 assert(object_id() == to->object_id());
00331 dword s1 = delinearize(seg);
00332 dword s2 = delinearize(((AddressX86_1616 *)to)->seg);
00333 if (s1 > s2) return 1;
00334 if (s1 < s2) return -1;
00335 dword a1 = delinearize(addr);
00336 dword a2 = delinearize(((AddressX86_1616 *)to)->addr);
00337 if (a1 > a2) return 1;
00338 if (a1 < a2) return -1;
00339 return 0;
00340 }
00341
00342 bool AddressX86_1616::difference(int &result, Address *to)
00343 {
00344 if ((object_id() == to->object_id()) && (seg == ((AddressX86_1616 *)to)->seg)) {
00345 result = (int)addr-(int)((AddressX86_1616 *)to)->addr;
00346 return true;
00347 } else {
00348 return false;
00349 }
00350 }
00351
00352 Object *AddressX86_1616::duplicate()
00353 {
00354 return new AddressX86_1616(seg, addr);
00355 }
00356
00357 void AddressX86_1616::getFromArray(const byte *array)
00358 {
00359 UNALIGNED_MOVE(addr, *(word*)array);
00360 UNALIGNED_MOVE(seg, *(word*)(array+sizeof addr));
00361 }
00362
00363 void AddressX86_1616::getFromCPUAddress(CPU_ADDR *ca)
00364 {
00365 seg = ca->addr32.seg;
00366 addr = ca->addr32.offset;
00367 }
00368
00369 int AddressX86_1616::load(ht_object_stream *s)
00370 {
00371 seg = s->getIntHex(2, NULL);
00372 addr = s->getIntHex(2, NULL);
00373 return s->get_error();
00374 }
00375
00376 OBJECT_ID AddressX86_1616::object_id() const
00377 {
00378 return ATOM_ADDRESS_X86_1616;
00379 }
00380
00381 int AddressX86_1616::parseString(const char *s, int length, Analyser *a)
00382 {
00383 return 0;
00384 }
00385
00386 void AddressX86_1616::putIntoArray(byte *array)
00387 {
00388 UNALIGNED_MOVE(*(word*)array, addr);
00389 UNALIGNED_MOVE(*(word*)(array+sizeof seg), seg);
00390 }
00391
00392 void AddressX86_1616::putIntoCPUAddress(CPU_ADDR *ca)
00393 {
00394 ca->addr32.seg = seg;
00395 ca->addr32.offset = addr;
00396 }
00397
00398 void AddressX86_1616::store(ht_object_stream *s)
00399 {
00400 s->putIntHex(seg, 2, NULL);
00401 s->putIntHex(addr, 2, NULL);
00402 }
00403
00404 int AddressX86_1616::stringify(char *s, int max_length, int format)
00405 {
00406 char *formats[] = {
00407 "%s%x%s:%s%04x%s",
00408 "%s%4x%s:%s%04x%s",
00409 "%s%04x%s:%s%04x%s",
00410 "",
00411 "%s%X%s:%s%04X%s",
00412 "%s%4X%s:%s%04X%s",
00413 "%s%04X%s:%s%04X%s",
00414 "",
00415 };
00416 return ht_snprintf(s, max_length, formats[format&7],
00417 (format & ADDRESS_STRING_FORMAT_ADD_0X) ? "0x":"", seg, (format & ADDRESS_STRING_FORMAT_ADD_H) ? "h":"",
00418 (format & ADDRESS_STRING_FORMAT_ADD_0X) ? "0x":"", addr, (format & ADDRESS_STRING_FORMAT_ADD_H) ? "h":"");
00419 }
00420
00421 int AddressX86_1616::stringSize()
00422 {
00423 return 9;
00424 }
00425
00426
00427
00428
00429 void AnalyX86Disassembler::init(Analyser *A, int f)
00430 {
00431 flags = f;
00432 createUnasm();
00433 AnalyDisassembler::init(A);
00434 }
00435
00436
00437
00438
00439 int AnalyX86Disassembler::load(ht_object_stream *f)
00440 {
00441 GET_INT_HEX(f, flags);
00442 return AnalyDisassembler::load(f);
00443 }
00444
00445
00446
00447
00448 void AnalyX86Disassembler::done()
00449 {
00450 AnalyDisassembler::done();
00451 }
00452
00453
00454
00455
00456 OBJECT_ID AnalyX86Disassembler::object_id() const
00457 {
00458 return ATOM_ANALY_X86;
00459 }
00460
00461 Address *AnalyX86Disassembler::createAddress(word segment, dword offset)
00462 {
00463 if (flags & ANALYX86DISASSEMBLER_FLAGS_FLAT64) {
00464 return new AddressFlat64(to_qword(offset));
00465 } else if (flags & ANALYX86DISASSEMBLER_FLAGS_SEGMENTED) {
00466 if (offset <= 0xffff) {
00467 return new AddressX86_1616(segment, offset);
00468 } else {
00469
00470
00471 return new AddressX86_1616(segment, offset);
00472 }
00473 } else {
00474 return new AddressX86Flat32(offset);
00475 }
00476 }
00477
00478 void AnalyX86Disassembler::createUnasm()
00479 {
00480 if (flags & ANALYX86DISASSEMBLER_FLAGS_VXD_X86DIS) {
00481 if (flags & ANALYX86DISASSEMBLER_FLAGS_16BIT) {
00482 disasm = new x86dis_vxd(X86_OPSIZE16, X86_ADDRSIZE16);
00483 } else {
00484 disasm = new x86dis_vxd(X86_OPSIZE32, X86_ADDRSIZE32);
00485 }
00486 } else {
00487 if (flags & ANALYX86DISASSEMBLER_FLAGS_16BIT) {
00488 disasm = new x86dis(X86_OPSIZE16, X86_ADDRSIZE16);
00489 } else {
00490 disasm = new x86dis(X86_OPSIZE32, X86_ADDRSIZE32);
00491 }
00492 }
00493 }
00494 word AnalyX86Disassembler::getSegment(Address *addr)
00495 {
00496 if (addr->object_id() == ATOM_ADDRESS_X86_1616) {
00497 return ((AddressX86_1616*)addr)->seg;
00498 } else if (addr->object_id() == ATOM_ADDRESS_X86_1632) {
00499 return ((AddressX86_1632*)addr)->seg;
00500 } else {
00501 assert(0);
00502 return 0;
00503 }
00504 }
00505
00506
00507
00508
00509 Address *AnalyX86Disassembler::branchAddr(OPCODE *opcode, branch_enum_t branchtype, bool examine)
00510 {
00511 Address *addr;
00512 x86dis_insn *o = (x86dis_insn*)opcode;
00513 assert(o->op[1].type == X86_OPTYPE_EMPTY);
00514 switch (o->op[0].type) {
00515 case X86_OPTYPE_IMM: {
00516
00517
00518
00519
00520 word seg = 0;
00521 if (flags & ANALYX86DISASSEMBLER_FLAGS_SEGMENTED) {
00522 seg = getSegment(analy->addr);
00523 }
00524 addr = createAddress(seg, o->op[0].imm);
00525 return addr;
00526 }
00527 case X86_OPTYPE_FARPTR:
00528 if (flags & ANALYX86DISASSEMBLER_FLAGS_SEGMENTED) {
00529 addr = createAddress(o->op[0].farptr.seg, o->op[0].farptr.offset);
00530 } else {
00531 break;
00532 }
00533 return addr;
00534 case X86_OPTYPE_MEM: {
00535 taccess access;
00536 addr = NULL;
00537 if (o->op[0].mem.hasdisp) {
00538 addr = createAddress(0, o->op[0].mem.disp);
00539 access.type = acread;
00540 access.indexed = (o->op[0].mem.base != X86_REG_NO) || (o->op[0].mem.index != X86_REG_NO);
00541 access.size = o->op[0].size;
00542 } else {
00543 break;
00544 }
00545 if (examine && analy->validAddress(addr, scvalid)) {
00546 analy->dataAccess(addr, access);
00547 xref_enum_t xref;
00548 switch (branchtype) {
00549 case br_jXX:
00550 case br_jump:
00551 xref = xrefijump;
00552 break;
00553 case br_call:
00554 xref = xreficall;
00555 break;
00556 default: {assert(0);}
00557 }
00558 analy->addXRef(addr, analy->addr, xref);
00559 }
00560 if (examine) {
00561 if (addr) delete addr;
00562 break;
00563 } else {
00564 return addr;
00565 }
00566 }
00567 }
00568 return new InvalidAddress();
00569 }
00570
00571
00572
00573
00574 void AnalyX86Disassembler::examineOpcode(OPCODE *opcode)
00575 {
00576 x86dis_insn *o = (x86dis_insn*)opcode;
00577 for (int i=0; i<3; i++) {
00578 x86_insn_op *op = &o->op[i];
00579 Address *addr = NULL;
00580 taccess access;
00581 xref_enum_t xref = xrefoffset;
00582 switch (op->type) {
00583 case X86_OPTYPE_IMM:
00584 access.type = acoffset;
00585 access.indexed = false;
00586 addr = createAddress(0, op->imm);
00587 break;
00588 case X86_OPTYPE_FARPTR:
00589 if (flags & ANALYX86DISASSEMBLER_FLAGS_SEGMENTED) {
00590 addr = createAddress(op->farptr.seg, op->farptr.offset);
00591 }
00592 access.type = acoffset;
00593 access.indexed = false;
00594 break;
00595 case X86_OPTYPE_MEM:
00596 if (op->mem.hasdisp) {
00597 addr = createAddress(0, op->mem.disp);
00598 access.type = acread;
00599 access.indexed = (op->mem.base != X86_REG_NO) || (op->mem.index != X86_REG_NO);
00600 access.size = op->size;
00601 if (strcmp(o->name, "cmp")==0 || strcmp(o->name, "test")==0 || strcmp(o->name, "push")==0) {
00602 xref = xrefread;
00603 } else {
00604 xref = (i==0) ? xrefwrite : xrefread;
00605 }
00606 }
00607 break;
00608 }
00609 if (addr) {
00610 if (analy->validAddress(addr, scvalid)) {
00611 analy->dataAccess(addr, access);
00612 analy->addXRef(addr, analy->addr, xref);
00613 }
00614 delete addr;
00615 }
00616 }
00617 }
00618
00619
00620
00621
00622 branch_enum_t AnalyX86Disassembler::isBranch(OPCODE *opcode)
00623 {
00624 x86dis_insn *o = (x86dis_insn*)opcode;
00625 char *opcode_str = o->name;
00626 if (opcode_str[0]=='j') {
00627 if (opcode_str[1]=='m') return br_jump; else return br_jXX;
00628 } else if ((opcode_str[0]=='l') && (opcode_str[1]=='o') && (opcode_str[2]=='o')) {
00629
00630 return br_jXX;
00631 } else if ((opcode_str[0]=='c') && (opcode_str[1]=='a')) {
00632 return br_call;
00633 } else if ((opcode_str[0]=='r') && (opcode_str[1]=='e')) {
00634 return br_return;
00635 } else return br_nobranch;
00636 }
00637
00638
00639
00640
00641 void AnalyX86Disassembler::store(ht_object_stream *f)
00642 {
00643 PUT_INT_HEX(f, flags);
00644 AnalyDisassembler::store(f);
00645 }
00646
00647