Page 2 of 2

Posted: Fri Jul 11, 2003 5:51 am
by dont_know_at_all
Updated in cvs and on the downloads page.

Posted: Fri Jul 11, 2003 6:06 am
by Plazmic
Servers just went down for another patch ;(

Posted: Fri Jul 11, 2003 7:22 am
by Valerian
and another eqgame.exe

Posted: Fri Jul 11, 2003 8:40 am
by javaspot
I don't know if this would help find offsets, but I have a program which can find a block of code in an exe even if the addresses change. The way it works is by removing the address part of the assembly instructions. Then you can give it another exe and it will find the same block of code even if it moved around and even if the addresses it references have been changed. It finds the block of code that had the same pattern moves, loads, saves, jumps, etc. I don't know how you guys are finding offsets, but would that program help you out?

Posted: Fri Jul 11, 2003 9:26 am
by motd2k
Wouldnt hurt to try it Java! That's basically the method I use, which is why the offsets were such a pain to find for 10th July.


MOTD

offsets for 11 july 2003 patch are here:

Posted: Fri Jul 11, 2003 9:28 am
by EqMule

Asmpat.java

Posted: Fri Jul 11, 2003 4:03 pm
by javaspot
Here are the programs I used to find blocks of code in a changed executable
--------------------------

Code for Asmpat.java -- Convert disassembled source code into a searchable pattern.

Build: javac Asmpat.java
Run: java Asmpat file_with_disassembled_block

The disassembled code must come from w32dsm.

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();
    }
}
}

Findpat.java

Posted: Fri Jul 11, 2003 4:07 pm
by javaspot
Code for Findpat.java -- Find code block matching pattern generated from Asmpat.java in a .exe file.

Build: javac Findpat.java
Run: java Findpat -p pattern_file exe_file

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());
            }
        }
        
        
        
    }
}