 |
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
BeansOfLight How do I cheat?
Reputation: 0
Joined: 09 Sep 2015 Posts: 9
|
Posted: Sun Dec 20, 2015 11:14 am Post subject: ASM Help |
|
|
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 |
|
 |
BeansOfLight How do I cheat?
Reputation: 0
Joined: 09 Sep 2015 Posts: 9
|
Posted: Mon Dec 21, 2015 7:31 am Post subject: |
|
|
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 |
|
 |
Gniarf Grandmaster Cheater Supreme
Reputation: 43
Joined: 12 Mar 2012 Posts: 1285
|
Posted: Mon Dec 21, 2015 1:24 pm Post subject: |
|
|
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 |
|
 |
BeansOfLight How do I cheat?
Reputation: 0
Joined: 09 Sep 2015 Posts: 9
|
Posted: Tue Dec 22, 2015 5:04 am Post subject: |
|
|
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 |
|
 |
Gniarf Grandmaster Cheater Supreme
Reputation: 43
Joined: 12 Mar 2012 Posts: 1285
|
Posted: Tue Dec 22, 2015 11:51 am Post subject: |
|
|
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 |
|
 |
BeansOfLight How do I cheat?
Reputation: 0
Joined: 09 Sep 2015 Posts: 9
|
Posted: Tue Dec 22, 2015 12:26 pm Post subject: |
|
|
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 |
|
 |
Gniarf Grandmaster Cheater Supreme
Reputation: 43
Joined: 12 Mar 2012 Posts: 1285
|
Posted: Tue Dec 22, 2015 2:35 pm Post subject: |
|
|
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 |
|
 |
BeansOfLight How do I cheat?
Reputation: 0
Joined: 09 Sep 2015 Posts: 9
|
Posted: Tue Dec 22, 2015 3:09 pm Post subject: |
|
|
Okay, great. Thanks for the help.
|
|
Back to top |
|
 |
|
|
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
|
|