Offsets 10 July - functional!

A forum for feature requests/discussions and user submitted patches that improve MQ2

Moderator: MacroQuest Developers

User avatar
dont_know_at_all
Developer
Developer
Posts: 5450
Joined: Sun Dec 01, 2002 4:15 am
Location: Florida, USA
Contact:

Post by dont_know_at_all » Fri Jul 11, 2003 5:51 am

Updated in cvs and on the downloads page.

Plazmic
The One
The One
Posts: 800
Joined: Fri Jun 14, 2002 12:31 am
Contact:

Post by Plazmic » Fri Jul 11, 2003 6:06 am

Servers just went down for another patch ;(
- Plazmic

Valerian
a grimling bloodguard
a grimling bloodguard
Posts: 709
Joined: Sun Jul 28, 2002 3:29 am

Post by Valerian » Fri Jul 11, 2003 7:22 am

and another eqgame.exe

javaspot
orc pawn
orc pawn
Posts: 25
Joined: Mon Oct 07, 2002 10:54 pm

Post by javaspot » Fri Jul 11, 2003 8:40 am

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?

motd2k
a ghoul
a ghoul
Posts: 141
Joined: Fri Oct 25, 2002 9:46 am

Post by motd2k » Fri Jul 11, 2003 9:26 am

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

EqMule
Developer
Developer
Posts: 2697
Joined: Fri Jan 03, 2003 9:57 pm
Contact:

offsets for 11 july 2003 patch are here:

Post by EqMule » Fri Jul 11, 2003 9:28 am

My status o/
If you like MQ2 and would like to contribute, please do. My goal is 25 donations per month.
So far I've received Image donations for this month's patches.

Bitcoin: 1Aq8ackjQ4f7AUvbUL7BE6oPfT8PmNP4Zq
Krono: PM me.
I can always use characters for testing, PM me if you can donate one.

javaspot
orc pawn
orc pawn
Posts: 25
Joined: Mon Oct 07, 2002 10:54 pm

Asmpat.java

Post by javaspot » Fri Jul 11, 2003 4:03 pm

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

javaspot
orc pawn
orc pawn
Posts: 25
Joined: Mon Oct 07, 2002 10:54 pm

Findpat.java

Post by javaspot » Fri Jul 11, 2003 4:07 pm

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