// filter to remove the garbage patterns // compile as "cl no_garbage.c map.c" // coded by bilbo - 30nov04 #include #include #include #include "map.h" BYTE call_pat[] = { 0x60, 0xE8, 0x48, 0x00, 0x00, 0x00 }; LPBYTE add; // global start of mapped file DWORD curbias; int instrlen(void) { LPBYTE p = add+curbias; LPBYTE p0 = p; int operandSize = 4; int FPU = 0; int twoByte = 0; // boolean unsigned char opcode; unsigned char modRM = 0xFF; while ( // skip prefixes F0h, F2h, F3h, 66h, 67h, D8h-DFh *p==0xF0 || *p==0xF2 || *p==0xF3 || (*p&0xFE) == 0x66 || (*p & 0xF8) == 0xD8 || // skip segment overrides 26,2E,36,3E,64,65 *p==0x26 || *p==0x2E || *p==0x36 || *p==0x3E || *p==0x64 || *p==0x65 ) { if (*p == 0x66) operandSize = 2; if((*p & 0xF8) == 0xD8) { FPU = *p++; break; } p++; } // skip two-byte opcode byte if (*p == 0x0F) { twoByte++; p++; } // assign opcode byte opcode = *p++; // assign mod R/M byte if present if (FPU) { if ((opcode & 0xC0) != 0xC0) modRM = opcode; } else if (!twoByte) { if ((opcode & 0xC4) == 0x00 || (opcode & 0xF4) == 0x60 && ((opcode & 0x0A) == 0x02 || (opcode & 0x09) == 0x9) || (opcode & 0xF0) == 0x80 || // 8B (opcode & 0xF8) == 0xC0 && (opcode & 0x0E) != 0x02 || (opcode & 0xFC) == 0xD0 || (opcode & 0xF6) == 0xF6) modRM = *p++; } else if ((opcode & 0xF0) == 0x00 && (opcode & 0x0F) >= 0x04 && (opcode & 0x0D) != 0x0D || (opcode & 0xF0) == 0x30 || opcode == 0x77 || (opcode & 0xF0) == 0x80 || (opcode & 0xF0) == 0xA0 && (opcode & 0x07) <= 0x02 || (opcode & 0xF8) == 0xC8); // no mod R/M byte else modRM = *p++; // assign SIB and displacement if((modRM & 0x07) == 0x04) { // SIB unsigned char SIB = *p; p += 1; if ((SIB & 0x7) == 5) p += 4; // disp32 (*bilbo*) } if((modRM & 0xC5) == 0x05) p += 4; // dword displacement, no base if((modRM & 0xC0) == 0x40) p += 1; // byte displacement if((modRM & 0xC0) == 0x80) p += 4; // dword displacement // skip immediate if (FPU); // can't have immediate operand else if (!twoByte) { if ((opcode & 0xC7) == 0x04 || (opcode & 0xFE) == 0x6A || // PUSH/POP/IMUL (opcode & 0xF0) == 0x70 || // Jcc opcode == 0x80 || opcode == 0x83 || (opcode & 0xFD) == 0xA0 || // MOV opcode == 0xA8 || // TEST (opcode & 0xB8) == 0xB0 || // MOV imm8 to r8 (*bilbo*) (opcode & 0xFE) == 0xC0 || // RCL opcode == 0xC6 || // MOV opcode == 0xCD || // INT (opcode & 0xFE) == 0xD4 || // AAD/AAM (opcode & 0xF8) == 0xE0 || // LOOP/JCXZ opcode == 0xEB || opcode == 0xF6 && (modRM & 0x30) == 0x00) // TEST p += 1; else if ((opcode & 0xF7) == 0xC2) p += 2; // RET else if ((opcode & 0xFC) == 0x80 || (opcode & 0xC7) == 0x05 || (opcode & 0xFE) == 0xE8 || // CALL/Jcc (opcode & 0xFE) == 0x68 || (opcode & 0xFC) == 0xA0 || (opcode & 0xEE) == 0xA8 || (opcode & 0xB8) == 0xB8 || // MOV imm16/32 to r16/32 (*bilbo*) opcode == 0xC7 || opcode == 0xF7 && (modRM & 0x30) == 0x00) p += operandSize; } else { if (opcode == 0xBA || // BT opcode == 0x0F || // 3DNow! (opcode & 0xFC) == 0x70 || // PSLLW (opcode & 0xF7) == 0xA4 || // SHLD opcode == 0xC2 || opcode == 0xC4 || opcode == 0xC5 || opcode == 0xC6) p += 1; else if ((opcode & 0xF0) == 0x80) p += operandSize; // Jcc -i } return p-p0; } int instrlen_inside(void) { LPBYTE p = add+curbias; switch (*p) { case 0x60/*PUSHAD*/: // prefixes case 0xF0: case 0xF2: case 0xF3: case 0x26: case 0x2E: case 0x36: case 0x3E: case 0x64: case 0x65: case 0x66: case 0x67: return 1; case 0x88: case 0x89: case 0x8A: case 0x8B: // MOV case 0xB0: case 0xB1: case 0xB2: case 0xB3: case 0xB4: case 0xB5: case 0xB6: case 0xB7: return 2; case 0xEB: // JMP assert(*(p+1) == 0x01); return 2+1; case 0xC6: return 3; case 0xB8: case 0xB9: case 0xBA: case 0xBB: case 0xBD: case 0xBE: case 0xBF: return 5; case 0x8D: case 0xC7: return 6; default: printf("unknown opcode %02x at %x\n", *p, 0xDE0000+curbias); assert(0); return 0; } } void main(void) { int found = 0; DWORD patternstart, patternend; map("0x90.exe"); add = addy; // initialize boundaries to the most internal layer for (curbias=0x8653; curbias<0x3BC77; curbias+=instrlen()) { #if 0 if (!memcmp(startaddr+curbias, call_pat, sizeof(call_pat)) && *(startaddr+curbias+0x67)==0x61) { printf("found call-pattern at %x-%x\n", 0xDE0000+curbias, 0xDE0000+curbias+0x67); curbias += 0x68; } else #endif if (*(add+curbias)==0x60 && *(add+curbias+1)!=0xE8) { found++; patternstart = curbias; do curbias += instrlen_inside(); while (*(add+curbias) != 0x61/*POPAD*/); patternend = curbias; memset(add+patternstart, 0x90, patternend-patternstart+1); } } printf("found %d patterns\n", found); }