Looks like you got the concept wrong. Pattern finding normally means find a piece of code not find some data that belongs to a class.
I will try to give you a little headstart with ida.
I will use the "ida style" text patterns that look like "E9 ? ? ? ? C8 ?". ? represents a wildcard. you could also write "E9 ?? ?? ?? ?? C8 ??" it´s both the same
Make a new folder, and copy your Diablo III.exe and ijl15.dll in it.
Open ida, and drag the exe in it. Select Pe-File and hit ok.
Now grab a cup of coffee and wait, till Ida finished analyzing it.
The IDA View-A window should now be active in graph view. Switch to Disassembly view by hitting SPACE
Go to the Menu Options->General and set Number of opcode bytes to 10.
now hit G and jump to address 0x00E60580. That´s the function that Allocates the Object Manager.
you should see the function it this representation:
address of instruction - bytecode of instruction - text representation of instruction
Code:
.text:00E60580 sub_E60580 proc near ; DATA XREF: .data:016AAA74o
.text:00E60580 53 push ebx
.text:00E60581 56 push esi
.text:00E60582 57 push edi
.text:00E60583 6A 01 push 1
.text:00E60585 33 FF xor edi, edi
.text:00E60587 57 push edi
.text:00E60588 6A 04 push 4
.text:00E6058A 68 88 09 00 00 push 988h // size of Object Manager
.text:00E6058F E8 8C 16 1B 00 call sub_1011C20 // memory allocation Function
.text:00E60594 83 C4 10 add esp, 10h
.text:00E60597 A3 C4 39 89 01 mov dword_18939C4, eax // pObjMgr
.text:00E6059C 8B F0 mov esi, eax
.text:00E6059E E8 DD 08 1C 00 call sub_1020E80
.text:00E605A3 8B 1D 0C 72 43 01 mov ebx, ds:TlsGetValue
.text:00E605A9 89 06 mov [esi], eax
.text:00E605AB 89 7E 04 mov [esi+4], edi
.text:00E605AE 89 7E 08 mov [esi+8], edi
.text:00E605B1 A1 C4 39 89 01 mov eax, dword_18939C4
.text:00E605B6 89 78 18 mov [eax+18h], edi
.text:00E605B9 8B 0D C4 39 89 01 mov ecx, dword_18939C4
.text:00E605BF C7 81 E4 03 00 00 FF FF FF FF mov dword ptr [ecx+3E4h], 0FFFFFFFFh
.text:00E605C9 8B 15 C4 39 89 01 mov edx, dword_18939C4
.text:00E605CF 89 BA E0 03 00 00 mov [edx+3E0h], edi
.text:00E605D5 A1 C4 39 89 01 mov eax, dword_18939C4
.text:00E605DA 89 B8 0C 04 00 00 mov [eax+40Ch], edi
.text:00E605E0 8B 0D 10 BC 6A 01 mov ecx, dwTlsIndex
.text:00E605E6 8B 35 C4 39 89 01 mov esi, dword_18939C4
.text:00E605EC 51 push ecx ; dwTlsIndex
.text:00E605ED 81 C6 8C 07 00 00 add esi, 78Ch
.text:00E605F3 FF D3 call ebx ; TlsGetValue
.text:00E605F5 8B 10 mov edx, [eax]
.text:00E605F7 C7 42 04 01 00 00 00 mov dword ptr [edx+4], 1
.text:00E605FE A1 10 BC 6A 01 mov eax, dwTlsIndex
.text:00E60603 50 push eax ; dwTlsIndex
.text:00E60604 FF D3 call ebx ; TlsGetValue
.text:00E60606 8B 08 mov ecx, [eax]
.text:00E60608 6A 01 push 1
.text:00E6060A 57 push edi
.text:00E6060B 6A 04 push 4
.text:00E6060D 68 A4 18 00 00 push 18A4h
.text:00E60612 89 31 mov [ecx], esi
.text:00E60614 E8 07 16 1B 00 call sub_1011C20
.text:00E60619 8B 15 C4 39 89 01 mov edx, dword_18939C4
.text:00E6061F 89 82 84 07 00 00 mov [edx+784h], eax
.text:00E60625 A1 C4 39 89 01 mov eax, dword_18939C4
.text:00E6062A 8B 88 84 07 00 00 mov ecx, [eax+784h]
.text:00E60630 51 push ecx
.text:00E60631 E8 AA F0 D2 FF call sub_B8F6E0
.text:00E60636 83 C4 14 add esp, 14h
.text:00E60639 5F pop edi
.text:00E6063A 5E pop esi
.text:00E6063B 5B pop ebx
.text:00E6063C C3 retn
.text:00E6063C sub_E60580 endp
Now about Creating patterns.
You need to create a pattern that will only be found once in the whole client and still be valid after a patch.
Let´s start with the function itself. Things that are most likely not changing between patches go into your pattern.
Things that are going to change (addresses, offsets and maybe arguments) are added as wildcards.
Code:
.text:00E60580 53 push ebx // 53 - unlikely to change
.text:00E60581 56 push esi // 56 - unlikely to change
.text:00E60582 57 push edi // 57 - unlikely to change
.text:00E60583 6A 01 push 1 // 6a ? - 1 may change. so wildcard it
.text:00E60585 33 FF xor edi, edi // 33 FF - unlikely to change
.text:00E60587 57 push edi // 57
.text:00E60588 6A 04 push 4 // 6A ?
.text:00E6058A 68 88 09 00 00 push 988h // 68 ? ? ? ? // size of ObjMgr can change -> wildcard
The resulting pattern is: "53 56 57 6A ? 33 FF 57 6A ? 68 ? ? ? ?"
Let´s test if it is unique. Menu->Search->sequence of bytes. enter the pattern and don´t forget to check "find all occurances"
If it´s unique great. else add a few more instructions to the pattern
DWORD addrFunctionAllocObjMgr = addrPattern.
DWORD sizeofObjMgr = *(DWORD*) (addrPattern + 11)
Now to the ObjMgrPtr
Code:
.text:00E6058A 68 88 09 00 00 push 988h // 68 ? ? ? ? // size of Object Manager
.text:00E6058F E8 8C 16 1B 00 call sub_1011C20 // E8 ? ? ? ?// memory allocation Function
.text:00E60594 83 C4 10 add esp, 10h // 83 C4 ?
.text:00E60597 A3 C4 39 89 01 mov dword_18939C4, eax // A3 ? ? ? ?// pObjMgr
.text:00E6059C 8B F0 mov esi, eax // 8B F0
Pattern: "68 ? ? ? ? E8 ? ? ? ? 83 C4 ? A3 ? ? ? ? 8B F0"
DWORD sizeofObjMgr = *(DWORD*) (addrPattern + 1)
DWORD pObjMgr = *(DWORD*) (addrPattern + 14)
i hope you got the concept.
If you want to make your life easyer, you can google for "SigMaker Ida" it´s a plugin that either creates pattern for the selected code or tries to create the shortest possible pattern that brings you to the position of your mouse. It´s not idiot proof and you sometimes have to add a few wildcards to it´s output but still makes things easyer.
Searching patterns by hand sucks. Counting bytes like (addrPattern + 14) also sucks. So here is my script finds patterns and sets itemnames:
Code:
#!/usr/bin/python2.6
#############################################
#
# Configure
#
#
# set to True to automatically rename items
renameMatches = True
# edit if different output is needed. or you want to log to file
def formatLogLine( function, name ):
return hex(function).upper() + "\t" + name + "\n"
#############################################
#
# Code
#
#
Message("\n######################\n")
Message("Starting Patternfinder\n\n")
#set search range to the segment the cursor is currently in
ea = ScreenEA()
eaStart = SegStart(ea)
eaEnd = SegEnd(ea)
# Find Pattern
# name obvious
# pattern ida style pattern to be searched
# numSkipInstr number of instructions to step forward/backward
# numOperant number of operant that contains the desired value. -1 if you just need the code address
def FindPattern( name, pattern, numSkipInstr = 0, numOperant = -1 ):
# find the pattern
addr = idaapi.find_binary(eaStart, eaEnd, pattern , 16,1)
if addr > 0 and numSkipInstr != 0:
# step x instructions for/backwards
for i in range(0, numSkipInstr):
if numSkipInstr > 0:
addr = NextHead(addr,eaEnd)
else:
addr = PrevHead(addr)
res = addr
if addr > 0 and numOperant != -1:
# extraxt operant value
res = GetOperandValue(addr, numOperant)
if res > 0:
Message( formatLogLine( res, name ))
if renameMatches == True:
if MakeName(res,name) == False:
MakeComm(addr,name)
else:
Message( "Failed to find Pattern " + name + "\n")
return
FindPattern("D3::AllocObjMgr", "53 56 57 6A ? 33 FF 57 6A 04 68 ? ? ? ?", 0, -1);
FindPattern("D3::AllocObjMgr", "53 56 57 6A 01 33 FF 57 6A 04 68 ? ? ? ?");
FindPattern("sizeOfObjMgr", "68 ? ? ? ? E8 ? ? ? ? 83 C4 ? A3 ? ? ? ? 8B F0", 0, 0)
FindPattern("D3::AllocateMemory", "68 ? ? ? ? E8 ? ? ? ? 83 C4 ? A3 ? ? ? ? 8B F0", 1, 0)
FindPattern("pObjMgr", "68 ? ? ? ? E8 ? ? ? ? 83 C4 ? A3 ? ? ? ? 8B F0", 3, 0)
FindPattern("pObjMgr", "68 ? ? ? ? E8 ? ? ? ? 83 C4 ? A3 ? ? ? ? 8B F0", 3, 0)
will: find the pattern -> travel 3 instructions forward -> read the value of the instruction's arg0
just hit ctrl + F7 copy/paste the script and run it.