Moderator: MacroQuest Developers

donations for this month's patches.Code: Select all
import java.io.*;
/**
This is a little program which can be used to create a "pattern" for a block
of assembly code. This pattern can then be used with the Findpat.java program
to locate that same block of code in a modified exe. So even if the block
moves to a different offset and if the offsets used within the block change,
the block can still be found in the new exe.
The input to this program is the text listing of the block of code from the
w32dsm disassmbly tool. For example, if this was the block of code you
were interested in:
:004016D6 8B935EDE0100 mov edx, dword ptr [ebx+0001DE5E]
:004016DC 85D2 test edx, edx
:004016DE 7412 je 004016F2
:004016E0 8B8BB1696000 mov ecx, dword ptr [ebx+006069B1]
:004016E6 85C9 test ecx, ecx
:004016E8 7608 jbe 004016F2
:004016EA 33C0 xor eax, eax
:004016EC 8983C4376F00 mov dword ptr [ebx+006F37C4], eax
You would save it to a file and then run Asmpat to process it. It would
output:
8B93........85D274..8B8B........85C976..33C08983........
Which is the block of code with all the addresses removed. You can then
give that pattern and an exe file to Findpat and it will print the offset
of that code block.
Usage:
Asmpat file_with_dasm_code
*/
public class Asmpat
{
public static String DOTS = ".......................................";
static byte[] binPattern = new byte[5000];
static int binIndex = 0;
public static void instructionToBin(String instruction)
{
int index;
for (index = 0; index < instruction.length(); index += 2)
{
String hex = instruction.substring(index, index + 2);
binPattern[binIndex++] = (byte) Integer.parseInt(hex, 16);
}
}
/**
Lines will look like one of the following:
1) :004AB225 E87F36FDFF call 0047E8A9
2) :004AB21F 8B0D8C837F00 mov ecx, dword ptr [007F838C]
3) :004AB21C 9E sahf
4) :004AB1EB 399810F30500 cmp dword ptr [eax+0005F310], ebx
*/
public static String convertToPattern(String line)
{
if (line == null || line.length() == 0 || line.charAt(0) != ':')
return (null);
String instruction;
String description;
int start;
int end;
//Find space after address
start = line.indexOf(' ');
//Find space after instruction
end = line.indexOf(' ', start + 1);
instruction = line.substring(start + 1, end);
instructionToBin(instruction);
start = end;
while (line.charAt(++start) == ' ');
//Now we 're pointing at the description
description = line.substring(start);
int addressStart = -1;
int addressEnd = -1;
boolean inBracket = false;
boolean inAddress = false;
//Find if there is an address.
start = 0;
for (start = 0; start < description.length(); start++)
{
char letter = description.charAt(start);
if (!inBracket && letter == '[')
{
inBracket = true;
continue;
}
if (inBracket && letter == ']')
{
inBracket = false;
continue;
}
if ((letter >= '0' && letter <= '9') ||
(letter >= 'A' && letter <= 'F'))
{
if (inAddress == false)
addressStart = start;
inAddress = true;
addressEnd = start;
if (inBracket == false)
{
//We found an non - bracketed address(Example #1 above).
// Just save the first two letters of the instruction since
// I don't know how to compute the rest of the instruction.
return (instruction.substring(0, 2) +
DOTS.substring(0, instruction.length() - 2));
}
}
}
if (addressStart > 0)
{
if (addressEnd - addressStart != 7)
{
System.err.println("Found address less than 8 bytes. aborting: " + description.substring(addressStart, addressEnd) + " " + description);
System.exit(1);
}
String address = description.substring(addressStart, addressEnd + 1);
//Rearrange the bytes for endian
StringBuffer fixedAddress = new StringBuffer();
fixedAddress.append(address.charAt(6));
fixedAddress.append(address.charAt(7));
fixedAddress.append(address.charAt(4));
fixedAddress.append(address.charAt(5));
fixedAddress.append(address.charAt(2));
fixedAddress.append(address.charAt(3));
fixedAddress.append(address.charAt(0));
fixedAddress.append(address.charAt(1));
if (instruction.endsWith(fixedAddress.toString()) == false)
{
System.err.println("The instruction did not end with: " + fixedAddress);
System.exit(1);
}
//Return everything but the last 8 bytes.(Last 8 bytes is address)
return (instruction.substring(0,
instruction.length()-8 ) + DOTS.substring(0,8 ));
}
//No address.Return full instruction.
return (instruction);
}
public static void main(String[] args) throws Exception
{
if (args.length == 0)
{
System.err.println("Usage AsmToPat [-o binoutput] asmoutput");
System.exit(1);
}
String binFile = null;
int argIndex;
for (argIndex = 0; argIndex < args.length; argIndex++)
{
if (args[argIndex].equals("-o"))
{
argIndex++;
binFile = args[argIndex];
}
else
break;
}
BufferedReader asmFile = new BufferedReader(new FileReader(args[argIndex]));
String line;
StringBuffer fullPattern = new StringBuffer();
while ((line = asmFile.readLine()) != null)
{
System.err.println(line);
String linePattern = convertToPattern(line);
System.err.println("-> " + linePattern);
if (linePattern == null)
continue;
fullPattern.append(linePattern);
}
System.out.println(fullPattern);
if (binFile != null)
{
FileOutputStream output = new FileOutputStream(binFile);
output.write(binPattern, 0, binIndex);
output.close();
}
}
}
Code: Select all
import java.io.*;
/**
*
Find a block of code in an exe.
You must first generate a pattern using the Asmpat program. Then
give that pattern and an exe to this program and it will try to find
the same block of code in the new exe.
The pattern might occur in multiple places so you might get multiple
offsets.
Usage: Findpat [pattern|-p patfile] exe
*/
public class Findpat
{
public static int START_ADDRESS = 0x00400000;
public static String readPatternFile(String patFile) throws Exception
{
BufferedReader reader = new BufferedReader(new FileReader(patFile));
return(reader.readLine());
}
public static int [] patternToBytes(String pattern)
{
int [] bytes = new int[pattern.length() / 2];
int index;
for (index = 0 ; index < pattern.length(); index += 2)
{
if (pattern.charAt(index) == '.')
{
bytes[index / 2] = -1 ;
continue;
}
String hex = pattern.substring(index,index + 2);
bytes[index / 2 ] = Integer.parseInt(hex,16);
}
return(bytes);
}
public static void main(String [] args) throws Exception
{
if (args.length < 2 )
{
System.err.println("Usage: Findpat [pattern|-p patfile] exe");
System.exit(1);
}
String pattern = null;
int argIndex;
for (argIndex = 0 ; argIndex < args.length ; argIndex++)
{
if (args[argIndex].equals("-p"))
{
argIndex++;
pattern = readPatternFile(args[argIndex]);
}
else
break;
}
if (pattern == null)
{
pattern = args[argIndex ++];
}
System.err.println("Searching in " + args[argIndex] + " for " + pattern);
int [] patternBytes = patternToBytes(pattern);
FileInputStream exeFile = new FileInputStream(args[argIndex]);
byte [] exeBytes = new byte[exeFile.available()];
exeFile.read(exeBytes);
int exeIndex;
int matches = 0;
for (exeIndex = 0 ; exeIndex <= exeBytes.length - patternBytes.length; exeIndex++)
{
// See if patterns match.
int loadAddress = START_ADDRESS + exeIndex;
int patIndex;
for (patIndex = 0 ; patIndex < patternBytes.length; patIndex++)
{
if (patternBytes[patIndex] == -1)
continue; // Wildcard
byte patByte = ((byte) (0xFF & patternBytes[patIndex]));
byte exeByte = exeBytes[exeIndex + patIndex];
if ( patByte == exeByte)
{
if (patIndex == 0)
{
/*
System.err.println("Maybe at: " +
Integer.toHexString(loadAddress));
if (loadAddress > 0x004ab000)
System.err.println("here");
*/
}
matches++;
continue;
}
break; // no match
}
if (patIndex >= patternBytes.length)
{
System.out.println("00" +
Integer.toHexString(exeIndex + START_ADDRESS).toUpperCase());
}
}
}
}