Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


ASM Help

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking
View previous topic :: View next topic  
Author Message
BeansOfLight
How do I cheat?
Reputation: 0

Joined: 09 Sep 2015
Posts: 9

PostPosted: Sun Dec 20, 2015 11:14 am    Post subject: ASM Help Reply with quote

Hi.

I'm looking at a case statement compiled from Delphi in the Cheat Engine debugger. I've managed to find the part I was looking for but is it possible to find out what the case was in its integer form? At the top of the case statement is the op code 'loop'.
Back to top
View user's profile Send private message
BeansOfLight
How do I cheat?
Reputation: 0

Joined: 09 Sep 2015
Posts: 9

PostPosted: Mon Dec 21, 2015 7:31 am    Post subject: Reply with quote

Sorry if I was a bit vague. Here is a simple example of what I'm confused by.

Code:

var
  someInt : Word;
begin
  case someInt of
    0 : ShowMessage('This is case 0');
    1 : ShowMessage('This is case 1');
    2 : ShowMessage('This is case 2');
    3, 4 : ShowMessage('This is case 3 and 4');
    6 : ShowMessage('This is case 6');
    5 : ShowMessage('This is case 5');
  end;
end;


Code:
http://postimg.org/image/kfeirsmwp
(I cant post an image)

How can I find out what 'someInt' is in each case as there is no cmp opcode?
Back to top
View user's profile Send private message
Gniarf
Grandmaster Cheater Supreme
Reputation: 43

Joined: 12 Mar 2012
Posts: 1285

PostPosted: Mon Dec 21, 2015 1:24 pm    Post subject: Reply with quote

Your switch looks like jmp dword [someInt*4+45a813] in assembly. At 45a813 there is an array of function pointers that determine what piece of code to execute for each someInt value.

So to find what someInt value corresponds to "This is case 6", you start by finding where case 6 starts (45a85B), then find 5b a8 45 00 in the array above case 0. Your function pointer is at 45a82B, and then you calculate its index in the array ( (45a82B-45a813)/sizeof(pointer)=6 ).

It's interesting to note that your compiler puts the pointer array before the subroutines, usually I see the array after the code.

_________________
DO NOT PM me if you want help on making/fixing/using a hack.
Back to top
View user's profile Send private message
BeansOfLight
How do I cheat?
Reputation: 0

Joined: 09 Sep 2015
Posts: 9

PostPosted: Tue Dec 22, 2015 5:04 am    Post subject: Reply with quote

Gniarf wrote:
Your switch looks like jmp dword [someInt*4+45a813] in assembly. At 45a813 there is an array of function pointers that determine what piece of code to execute for each someInt value.

So to find what someInt value corresponds to "This is case 6", you start by finding where case 6 starts (45a85B), then find 5b a8 45 00 in the array above case 0. Your function pointer is at 45a82B, and then you calculate its index in the array ( (45a82B-45a813)/sizeof(pointer)=6 ).

It's interesting to note that your compiler puts the pointer array before the subroutines, usually I see the array after the code.


Thanks very much for your help. I managed to figure it out yesterday using the same method but I was worried about one thing. What would happen if there was a gap in the switch and it didn't increment by 1 each time?

eg
Code:

  case someInt of
    0 :
    5 : 
    500 :   
  end;


- edit. For something like that it looks like the compiler didn't make an array of pointers like there was in the first example. In the process I'm trying to change there is an array, does this mean I can assume they all increment by 1?
Back to top
View user's profile Send private message
Gniarf
Grandmaster Cheater Supreme
Reputation: 43

Joined: 12 Mar 2012
Posts: 1285

PostPosted: Tue Dec 22, 2015 11:51 am    Post subject: Reply with quote

I once saw a switch that had 2 arrays: one that contained the function pointers, and one that contained indexes for each case.
Basically something like:
Code:
case someInt of
    0,8 : Func1
    1,3 : Func2
    2 : Func3
end;
became something like:
Code:
FunctionPtrArray={PtrToFunc1, PtrToFunc2, PtrToFunc3, PtrToDefaultFunc};
IndexMap={0,1,2,1,3,3,3,3,0};
call FunctionPtrArray[IndexMap[someInt]];
With some additional checks to avoid array overflows.

Anyway, jmp [eax*4+123456] requires writing 123456 as a dword in the code, so once you have the pointer array you can scan for the address where it begins and find the code that references it. From there figuring how the switch works should be rather easy.

_________________
DO NOT PM me if you want help on making/fixing/using a hack.
Back to top
View user's profile Send private message
BeansOfLight
How do I cheat?
Reputation: 0

Joined: 09 Sep 2015
Posts: 9

PostPosted: Tue Dec 22, 2015 12:26 pm    Post subject: Reply with quote

Gniarf wrote:
I once saw a switch that had 2 arrays: one that contained the function pointers, and one that contained indexes for each case.
Basically something like:
Code:
case someInt of
    0,8 : Func1
    1,3 : Func2
    2 : Func3
end;
became something like:
Code:
FunctionPtrArray={PtrToFunc1, PtrToFunc2, PtrToFunc3, PtrToDefaultFunc};
IndexMap={0,1,2,1,3,3,3,3,0};
call FunctionPtrArray[IndexMap[someInt]];
With some additional checks to avoid array overflows.



If the gaps were larger than in the example above it would be a rather large array if it had to make a default for everything that isn't used. Did my compiler decide to ignore my switch statement and just check everything individually?

Code:
http://s7.postimg.org/sywuu57wr/cepic2.png
Again cant post urls.


Going back to what you said about the index map. Would the data for this be located at a set point before the first pointer in the array?
Back to top
View user's profile Send private message
Gniarf
Grandmaster Cheater Supreme
Reputation: 43

Joined: 12 Mar 2012
Posts: 1285

PostPosted: Tue Dec 22, 2015 2:35 pm    Post subject: Reply with quote

BeansOfLight wrote:
Did my compiler decide to ignore my switch statement and just check everything individually?
Actually this is the most common implementation of switches. I don't know if you have already coded a WindowProc function but it's basically an enormous switch(MessageSentToAWindow), and each time I find this function in a program, it's a bunch of subtractions and jumps.
But yeah, basically when there are too many gaps the compiler gives up on fast array access and turns your switch into a bunch of tests.

BeansOfLight wrote:
Going back to what you said about the index map. Would the data for this be located at a set point before the first pointer in the array?
Just found a game that has a 2 array switch: spintires.
The game was compiled under visual C 2008, blocks are in this order: switch statement, case handlers, pointer array, and then index map. Here is how it looks like:
Code:
005AD5D0  /$ 53                PUSH EBX            ;function begin
005AD5D1  |. 8B5C24 0C         MOV EBX,DWORD PTR [ESP+C]
005AD5D5  |. 56                PUSH ESI
005AD5D6  |. 8B7424 0C         MOV ESI,DWORD PTR [ESP+C]
005AD5DA  |. 3BF3              CMP ESI,EBX
005AD5DC  |. 73 5D             JNB SHORT 005AD63B
005AD5DE  |. 57                PUSH EDI
005AD5DF  |. 8B7C24 18         MOV EDI,DWORD PTR [ESP+18]
005AD5E3  |> 8B06              /MOV EAX,DWORD PTR [ESI]
005AD5E5  |. 83F8 15           |CMP EAX,15
005AD5E8  |. 72 49             |JB SHORT 005AD633
005AD5EA  |. 50                |PUSH EAX
005AD5EB  |. 50                |PUSH EAX
005AD5EC  |. 68 34B0C900       |PUSH 00C9B034
005AD5F1  |. 8BCF              |MOV ECX,EDI
005AD5F3  |. E8 08130100       |CALL 005BE900
005AD5F8  |. 8B06              |MOV EAX,DWORD PTR [ESI]
005AD5FA  |. 0FBE00            |MOVSX EAX,BYTE PTR [EAX]
005AD5FD  |. 83C0 BB           |ADD EAX,-45         ;  Switch (cases 45..70)
005AD600  |. 83F8 2B           |CMP EAX,2B
005AD603  |. 77 35             |JA SHORT 005AD63A
005AD605  |. 0FB688 54D65A00   |MOVZX ECX,BYTE PTR [EAX+5AD654]
005AD60C  |. FF248D 40D65A00   |JMP DWORD PTR [ECX*4+5AD640]
005AD613  |> 83C6 0C           |ADD ESI,0C         ;  Cases 45,53,54,6C of switch 005AD5FD
005AD616  |. EB 1E             |JMP SHORT 005AD636
005AD618  |> 8B46 0C           |MOV EAX,DWORD PTR [ESI+C]   ;  Cases 4C,4F of switch 005AD5FD
005AD61B  |. 50                |PUSH EAX
005AD61C  |. 50                |PUSH EAX
005AD61D  |. 68 34B0C900       |PUSH 00C9B034
005AD622  |. 8BCF              |MOV ECX,EDI
005AD624  |. E8 D7120100       |CALL 005BE900
005AD629  |. 83C6 10           |ADD ESI,10
005AD62C  |. EB 08             |JMP SHORT 005AD636
005AD62E  |> 83C6 08           |ADD ESI,8         ;  Case 4D of switch 005AD5FD
005AD631  |. EB 03             |JMP SHORT 005AD636
005AD633  |> 83C6 04           |ADD ESI,4         ;  Cases 4E ,50 ,70 of switch 005AD5FD
005AD636  |> 3BF3              |CMP ESI,EBX
005AD638  |.^72 A9             \JB SHORT 005AD5E3
005AD63A  |> 5F                POP EDI            ;  Default case of switch 005AD5FD
005AD63B  |> 5E                POP ESI
005AD63C  |. 5B                POP EBX
005AD63D  \. C3                RETN            ;function end
005AD63E     8BFF              MOV EDI,EDI         ;padding to 32-bit align the pointer array
005AD640   . 13D65A00          DD 005AD613         ;  Switch table
005AD644   . 18D65A00          DD 005AD618
005AD648   . 2ED65A00          DD 005AD62E
005AD64C   . 33D65A00          DD 005AD633
005AD650   . 3AD65A00          DD 005AD63A
005AD654   . 00                DB 00            ;  Index table
005AD655   . 04                DB 04
005AD656   . 04                DB 04
005AD657   . 04                DB 04
005AD658   . 04                DB 04
005AD659   . 04                DB 04
005AD65A   . 04                DB 04
005AD65B   . 01                DB 01
005AD65C   . 02                DB 02
005AD65D   . 03                DB 03
005AD65E   . 01                DB 01
005AD65F   . 03                DB 03
005AD660   . 04                DB 04
005AD661   . 04                DB 04
005AD662   . 00                DB 00
005AD663   . 00                DB 00
005AD664   . 04                DB 04
005AD665   . 04                DB 04
005AD666   . 04                DB 04
005AD667   . 04                DB 04
005AD668   . 04                DB 04
005AD669   . 04                DB 04
005AD66A   . 04                DB 04
005AD66B   . 04                DB 04
005AD66C   . 04                DB 04
005AD66D   . 04                DB 04
005AD66E   . 04                DB 04
005AD66F   . 04                DB 04
005AD670   . 04                DB 04
005AD671   . 04                DB 04
005AD672   . 04                DB 04
005AD673   . 04                DB 04
005AD674   . 04                DB 04
005AD675   . 04                DB 04
005AD676   . 04                DB 04
005AD677   . 04                DB 04
005AD678   . 04                DB 04
005AD679   . 04                DB 04
005AD67A   . 04                DB 04
005AD67B   . 00                DB 00
005AD67C   . 04                DB 04
005AD67D   . 04                DB 04
005AD67E   . 04                DB 04
005AD67F   . 03                DB 03
Note: most comments were autogenerated by ollydbg.
_________________
DO NOT PM me if you want help on making/fixing/using a hack.
Back to top
View user's profile Send private message
BeansOfLight
How do I cheat?
Reputation: 0

Joined: 09 Sep 2015
Posts: 9

PostPosted: Tue Dec 22, 2015 3:09 pm    Post subject: Reply with quote

Okay, great. Thanks for the help.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites