I have already been using Easyhook in C# to hook functions of the WINAPI.
Now I am trying to hook an internal function of a program to log a specific "event".
I have been able to discover the function call with the "Ultimap"-Function of Cheat Engine:
008AEC40 /$ 6A FF PUSH -1
008AEC42 |. 68 E37EC100 PUSH Progra.00C17EE3
008AEC47 |. 64:A1 00000000 MOV EAX,DWORD PTR FS:[0]
008AEC4D |. 50 PUSH EAX
008AEC4E |. 51 PUSH ECX
008AEC4F |. 56 PUSH ESI
008AEC50 |. A1 4093F600 MOV EAX,DWORD PTR DS:[F69340]
008AEC55 |. 33C4 XOR EAX,ESP
008AEC57 |. 50 PUSH EAX
008AEC58 |. 8D4424 0C LEA EAX,DWORD PTR SS:[ESP+C]
008AEC5C |. 64:A3 00000000 MOV DWORD PTR FS:[0],EAX
008AEC62 |. 8BF1 MOV ESI,ECX
008AEC64 |. 897424 08 MOV DWORD PTR SS:[ESP+8],ESI
008AEC68 |. E8 033CFFFF CALL Progra.008A2870
008AEC6D |. C74424 14 0000000>MOV DWORD PTR SS:[ESP+14],0
008AEC75 |. 8B4424 1C MOV EAX,DWORD PTR SS:[ESP+1C]
008AEC79 |. 50 PUSH EAX
008AEC7A |. 8D4E 24 LEA ECX,DWORD PTR DS:[ESI+24]
008AEC7D |. C706 18E8CD00 MOV DWORD PTR DS:[ESI],Progra.00CDE818
008AEC83 |. E8 F8E7FFFF CALL Progra.008AD480
008AEC88 |. C74424 14 FFFFFFF>MOV DWORD PTR SS:[ESP+14],-1
008AEC90 |. 8BC6 MOV EAX,ESI
008AEC92 |. 8B4C24 0C MOV ECX,DWORD PTR SS:[ESP+C]
008AEC96 |. 64:890D 00000000 MOV DWORD PTR FS:[0],ECX
008AEC9D |. 59 POP ECX
008AEC9E |. 5E POP ESI
008AEC9F |. 83C4 10 ADD ESP,10
008AECA2 \. C2 0400 RETN 4
The function gets called here:
008CAF5F . 85F6 TEST ESI,ESI
008CAF61 . 74 29 JE SHORT Progra.008CAF8C
008CAF63 . 6A 32 PUSH 32
008CAF65 . 8D5424 4C LEA EDX,DWORD PTR SS:[ESP+4C]
008CAF69 . 52 PUSH EDX
008CAF6A . 8D8F DC120000 LEA ECX,DWORD PTR DS:[EDI+12DC]
008CAF70 . E8 2BF4F4FF CALL Progra.0081A3A0
008CAF75 . C68424 A4000000 1>MOV BYTE PTR SS:[ESP+A4],13
008CAF7D . 834C24 14 40 OR DWORD PTR SS:[ESP+14],40
008CAF82 . 50 PUSH EAX
008CAF83 . 8BCE MOV ECX,ESI
008CAF85 . E8 B63CFEFF CALL Progra.008AEC40 #### FUNCTION CALL ####
008CAF8A . EB 02 JMP SHORT Progra.008CAF8E
008CAF8C > 33C0 XOR EAX,EAX
008CAF8E > C78424 A4000000 1>MOV DWORD PTR SS:[ESP+A4],14
008CAF99 . 8B95 F0130000 MOV EDX,DWORD PTR SS:[EBP+13F0]
008CAF9F . 6A 01 PUSH 1
008CAFA1 . 8D7424 38 LEA ESI,DWORD PTR SS:[ESP+38]
Right now I am trying to learn more about ASM (calling conventions etc.). This tutorial is very good but I still don' t know how to deal with the function above.
How might the function argument(s) look like?
When breaking at the function call, the information (a simple Integer) I try to "extract" via hooking is stored in EBX, which unfortunately isn' t accessed once. So I have look for a function, where this value is passed as an argument, right?
The function 008AEC40 appears to be using the thiscall calling convention. The first argument, the this pointer is passed in ECX. The rest of the arguments are pushed on the the stack in right to left order. This particular function, a method of C++ class, only takes one argument in addition to its implicit this pointer.
Related
ollydbg access violation when writing into 0000057C
Below code give me error as it write null empty exp date how i can pass this or make it type fixed date
00ABF6C1 C683 7C050000 >MOV BYTE PTR DS:[EBX+57C],1
00ABF6C8 . 8BC3 MOV EAX,EBX
00ABF6CA . E8 BDAD94FF CALL playerb2.0040A48C
00ABF6CF > 33C0 XOR EAX,EAX
00ABF6D1 . 5A POP EDX
00ABF6D2 . 59 POP ECX
00ABF6D3 . 59 POP ECX
00ABF6D4 . 64:8910 MOV DWORD PTR FS:[EAX],EDX
00ABF6D7 . 68 ECF6AB00 PUSH playerb2.00ABF6EC
00ABF6DC > 8D45 FC LEA EAX,DWORD PTR SS:[EBP-4]
00ABF6DF . E8 A8AD94FF CALL playerb2.0040A48C
00ABF6E4 . C3 RETN
00ABF6E5 .^E9 42A394FF JMP playerb2.00409A2C
00ABF6EA .^EB F0 JMP SHORT playerb2.00ABF6DC
00ABF6EC . 5B POP EBX
00ABF6ED . 59 POP ECX
00ABF6EE . 5D POP EBP
00ABF6EF . C3 RETN
I attached my asm into my source code of dll and hooked it to my exe, and it works like a charm but when I packed my exe using exe packer. the dll with asm not working on exe packed. any idea how to solve this problem?
#include "StdAfx.h"
void __declspec(naked) MyStuff() {
__asm {
PUSH EBP
MOV EBP, ESP
MOV EAX, DWORD PTR SS : [EBP + 0x8]
MOV EAX, DWORD PTR DS : [EAX]
XOR EAX, ENCPACKET
MOV DWORD PTR SS : [EBP + 0x8], EAX
MOV AX, WORD PTR SS : [EBP + 0xA]
POP EBP
RETN 0x4
}
}
void SetStuff(){
SetJmp((LPVOID)0x00424B1C, MyStuff);
}
The result was:
005DB4E0 /> \55 PUSH EBP
005DB4E1 |. 8BEC MOV EBP,ESP
005DB4E3 |. 56 PUSH ESI
005DB4E4 |. FF75 0C PUSH DWORD PTR SS:[EBP+C]
005DB4E7 |. B9 403E0801 MOV ECX,01083E40
005DB4EC |. E8 38CCE3FF CALL 00418129
005DB4F1 |. 8BF0 MOV ESI,EAX
005DB4F3 |. 85F6 TEST ESI,ESI
005DB4F5 |. 74 1E JE SHORT 005DB515
005DB4F7 |. FF75 08 PUSH DWORD PTR SS:[EBP+8]
005DB4FA |. 8BCE MOV ECX,ESI
005DB4FC |. E8 D799E4FF CALL 00424ED8
005DB501 |. 8B4D 10 MOV ECX,DWORD PTR SS:[EBP+10]
005DB504 |. FF75 08 PUSH DWORD PTR SS:[EBP+8]
005DB507 |. 8901 MOV DWORD PTR DS:[ECX],EAX
005DB509 |. 8BCE MOV ECX,ESI
005DB50B |. E8 EEA5E4FF CALL 00425AFE
005DB510 |. 8B4D 14 MOV ECX,DWORD PTR SS:[EBP+14]
005DB513 |. 8901 MOV DWORD PTR DS:[ECX],EAX
005DB515 |> 5E POP ESI
005DB516 |. 5D POP EBP
005DB517 \. C2 1000 RETN 10
and may I ask is it possible to run an asm into specific offset like this?
#include "StdAfx.h"
void __declspec(naked) MyStuff() {
__asm {
005DB4E0-> PUSH EBP
005DB4E1-> MOV EBP, ESP
005DB4E3-> MOV EAX, DWORD PTR SS : [EBP + 0x8]
005DB4E4-> MOV EAX, DWORD PTR DS : [EAX]
005DB4E7-> XOR EAX, ENCPACKET
005DB4EC-> MOV DWORD PTR SS : [EBP + 0x8], EAX
005DB4E1-> MOV AX, WORD PTR SS : [EBP + 0xA]
005DB4F3-> POP EBP
005DB4F4-> RETN 0x4
}
}
I would like to dump a functions memory (void) to a byte array (unsinged char[]). Aftwerwards, a dummy function shall be pointed to the byte array and the dummy function shall be executed.
The function I want to dump:
void CallMessageBoxExA()
{
message = "ManualMessageBoxExA";
caption = "Caption";
pAddr = GetProcAddress(GetModuleHandle(L"User32.dll"), "MessageBoxExA");
__asm // Call MessageBoxA
{
push dword ptr 0 //--- push languageID: 0
push dword ptr 0 //--- push style: 0
push dword ptr caption //--- push DWORD parameter (caption)
push dword ptr message //--- push DWORD parameter (message)
push dword ptr 0 //--- push hOwner: 0
mov eax, pAddr
call eax //-- call address of the function, which is currently in EAX
}
}
Dumping the memory:
string DumpMemory(void *pAddress, int maxLength)
{
string result = "";
const unsigned char * p = reinterpret_cast< const unsigned char *>(pAddress);
cout << "Memory location: 0x" << hex << (unsigned int)p << endl;
for (unsigned int i = 0; i < maxLength; i++) {
string code = "";
stringstream ss;
ss << hex << int(p[i]);
ss >> code;
result += code;
}
return result;
}
When looking at the memory location DumpMemory prints to the console, ollydbg shows a JMP instruction at this location:
CPU Disasm
Address Hex dump Command Comments
00281627 $-/E9 044C0000 JMP CallMessageBoxExA
Is this the correct memory-location, or do I have to follow the JMP?
Memory location jump leads to:
CPU Disasm
Address Hex dump Command Comments
00286230 /$ 55 PUSH EBP ; ASM.CallMessageBoxExA(void)
00286231 |. 8BEC MOV EBP,ESP
00286233 |. 81EC C0000000 SUB ESP,0C0
00286239 |. 53 PUSH EBX
0028623A |. 56 PUSH ESI
0028623B |. 57 PUSH EDI
0028623C |. 8DBD 40FFFFFF LEA EDI,[EBP-0C0]
00286242 |. B9 30000000 MOV ECX,30
00286247 |. B8 CCCCCCCC MOV EAX,CCCCCCCC
0028624C |. F3:AB REP STOS DWORD PTR ES:[EDI]
0028624E |. C705 A8562900 MOV DWORD PTR DS:[message],OFFSET 00291D ; ASCII "ManualMessageBoxExA"
00286258 |. C705 AC562900 MOV DWORD PTR DS:[caption],OFFSET 00291D ; ASCII "Caption"
00286262 |. 8BF4 MOV ESI,ESP
00286264 |. 68 041E2900 PUSH OFFSET 00291E04 ; ASCII "MessageBoxExA"
00286269 |. 8BFC MOV EDI,ESP
0028626B |. 68 D01D2900 PUSH OFFSET 00291DD0 ; /ModuleName = "User32.dll"
00286270 |. FF15 00602900 CALL DWORD PTR DS:[<&KERNEL32.GetModuleH ; \KERNEL32.GetModuleHandleW
00286276 |. 3BFC CMP EDI,ESP
00286278 |. E8 5BB2FFFF CALL 002814D8 ; [_RTC_CheckEsp
0028627D |. 50 PUSH EAX ; |hModule
0028627E |. FF15 04602900 CALL DWORD PTR DS:[<&KERNEL32.GetProcAdd ; \KERNEL32.GetProcAddress
00286284 |. 3BF4 CMP ESI,ESP
00286286 |. E8 4DB2FFFF CALL 002814D8 ; [_RTC_CheckEsp
0028628B |. A3 B0562900 MOV DWORD PTR DS:[pAddr],EAX
00286290 |. 6A 00 PUSH 0
00286292 |. 6A 00 PUSH 0
00286294 |. FF35 AC562900 PUSH DWORD PTR DS:[caption]
0028629A |. FF35 A8562900 PUSH DWORD PTR DS:[message]
002862A0 |. 6A 00 PUSH 0
002862A2 |. A1 B0562900 MOV EAX,DWORD PTR DS:[pAddr]
002862A7 |. FFD0 CALL EAX
002862A9 |. 5F POP EDI
002862AA |. 5E POP ESI
002862AB |. 5B POP EBX
002862AC |. 81C4 C0000000 ADD ESP,0C0
002862B2 |. 3BEC CMP EBP,ESP
002862B4 |. E8 1FB2FFFF CALL 002814D8 ; [_RTC_CheckEsp
002862B9 |. 8BE5 MOV ESP,EBP
002862BB |. 5D POP EBP
002862BC \. C3 RETN
Pointing the dummy function at the byte array:
void(*func_ptr)();
func_ptr = (void(*)()) &foo[0]; // make function point to foo[]
(*func_ptr)(); // Call the function
Is this the correct way to make the dummy function point to the byte array?
At which point is the function's end reached? Should I simply check for the different return opcodes (C3 -> return near to caller, CB -> return far to caller, ...)?
PS:
A simple (e.g. not very elaborate) solution is preferred as I am new to C++.
Edit: I want to achieve this in a Windows environment.
You need to store the "copied" function on a block of memory allocated using VirtualAllocEx. On modern OSs, there is a bit on each page which declares whether its contents are executable or not. This is used to minimize the damage of buffer overruns. By default, your memory is not executable. If you use VirtualAllocEx with the PAGE_EXECUTE_READWRITE protection mode, you'll be able to write to a block of memory and then execute from it.
As for your question of "when do you reach the end of a function," that is actually not answerable. There are common patterns you can look for, but x86 lacks any way of identifying the "end" of a function.
It looks like you need to follow the jump. When you follow the jump, the code you're seeing matches what you compiled above.
Also, your DumpMemory is using the address of pAddressIn. Your function is being passed a variable called pAddress. Either this is a typo, or you're referencing a variable declared somewhere else. I assume you meant to use pAddress.
The memory you allocate may need special privilege to be allowed to run. As is, the memory you allocate with the raw function data will be marked as "data". "Data Execution Prevention" may stop this depending on your environment.
Is there any difference in computational cost of
if(something){
return something;
}else{
return somethingElse;
}
and
if(something){
return something;
}
//else (put in comments for readibility purposes)
return somethingElse;
In theory we have command (else) but it doesn't seem it should make an actuall difference.
Edit:
After running code for different set sizes, I found that there actually is a differrence, code without else appears to be about 1.5% more efficient. But it most likely depends on compiler, as stated by many people below. Code I tested it on:
int withoutElse(bool a){
if(a)
return 0;
return 1;
}
int withElse(bool a){
if(a)
return 0;
else
return 1;
}
int main(){
using namespace std;
bool a=true;
clock_t begin,end;
begin= clock();
for(__int64 i=0;i<1000000000;i++){
a=!a;
withElse(a);
}
end = clock();
cout<<end-begin<<endl;
begin= clock();
for(__int64 i=0;i<1000000000;i++){
a=!a;
withoutElse(a);
}
end = clock();
cout<<end-begin<<endl;
return 0;
}
Checked on loops from 1 000 000 to 1 000 000 000, and results were consistently different
Edit 2:
Assembly code (once again, generated using Visual Studio 2010) also shows small difference (appareantly, I'm no good with assemblers :()
?withElse##YAH_N#Z PROC ; withElse, COMDAT
; Line 12
push ebp
mov ebp, esp
sub esp, 192 ; 000000c0H
push ebx
push esi
push edi
lea edi, DWORD PTR [ebp-192]
mov ecx, 48 ; 00000030H
mov eax, -858993460 ; ccccccccH
rep stosd
; Line 13
movzx eax, BYTE PTR _a$[ebp]
test eax, eax
je SHORT $LN2#withElse
; Line 14
xor eax, eax
jmp SHORT $LN3#withElse
; Line 15
jmp SHORT $LN3#withElse
$LN2#withElse:
; Line 16
mov eax, 1
$LN3#withElse:
; Line 17
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 0
?withElse##YAH_N#Z ENDP ; withElse
and
?withoutElse##YAH_N#Z PROC ; withoutElse, COMDAT
; Line 4
push ebp
mov ebp, esp
sub esp, 192 ; 000000c0H
push ebx
push esi
push edi
lea edi, DWORD PTR [ebp-192]
mov ecx, 48 ; 00000030H
mov eax, -858993460 ; ccccccccH
rep stosd
; Line 5
movzx eax, BYTE PTR _a$[ebp]
test eax, eax
je SHORT $LN1#withoutEls
; Line 6
xor eax, eax
jmp SHORT $LN2#withoutEls
$LN1#withoutEls:
; Line 7
mov eax, 1
$LN2#withoutEls:
; Line 9
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 0
?withoutElse##YAH_N#Z ENDP ; withoutElse
It is generically different, but the compiler may decide to execute the same jump in both cases (it will practically do this always).
The best way to see what a compiler does is reading the assembler. Assuming that you are using gcc you can try with
gcc -g -c -fverbose-asm myfile.c; objdump -d -M intel -S myfile.o > myfile.s
which creates a mix of assembler/c code and makes the job easier at the beginning.
As for your example it is:
CASE1
if(something){
23: 83 7d fc 00 cmp DWORD PTR [ebp-0x4],0x0
27: 74 05 je 2e <main+0x19>
return something;
29: 8b 45 fc mov eax,DWORD PTR [ebp-0x4]
2c: eb 05 jmp 33 <main+0x1e>
}else{
return 0;
2e: b8 00 00 00 00 mov eax,0x0
}
CASE2
if(something){
23: 83 7d fc 00 cmp DWORD PTR [ebp-0x4],0x0
27: 74 05 je 2e <main+0x19>
return something;
29: 8b 45 fc mov eax,DWORD PTR [ebp-0x4]
2c: eb 05 jmp 33 <main+0x1e>
return 0;
2e: b8 00 00 00 00 mov eax,0x0
As you could imagine there are no differences!
It won't compile if you type `return
Think that once the code gets compiled, all ifs, elses and loops are changed to goto's
If (cond) { code A } code B
turns to
if cond is false jump to code b
code A
code B
and
If (cond) { code A } else { code B } code C
turns to
if cond is false jump to code B
code A
ALWAYS jump to code C
code B
code C
Most processors 'guess' whether they're going to jump or not before checking if they actually jump. Depending on the processor, it might affect the performance to fail a guess.
So the answer is YES! (unless there's an ALWAYS jump at the end of first comparison) It will take 2-3 cycles to do the ALWAYS jump which isn't in the first if.
I've just written a bubble_sort of an integer array (see previous question) and decided to ignore the standard swap and implement an assembly swap, which looks like this:
int swap(int* x, int* y)
{
if(x != y)
{
_asm
{
mov eax,[x];
mov ebx, [y];
mov [y],eax;
mov [x], ebx;
}
}
return 0;
}
I was actually sure that it will be inserted into the resulting code as is and will work.
Well, my code which uses this swap does work, but I've looked into what the complier turned it into, and my swap was changed into this:
if(x != y)
00E01A6F inc ebp
00E01A70 or byte ptr [ebx],bh
00E01A72 inc ebp
00E01A73 or al,74h
if(x != y)
00E01A75 or al,8Bh
{
_asm
{
mov eax,[x];
00E01A77 inc ebp
00E01A78 or byte ptr [ebx+45890C5Dh],cl
mov [y],eax;
00E01A7E or al,89h
mov [x], ebx;
00E01A80 pop ebp
00E01A81 or byte ptr [ebx],dh
}
}
return 0;
00E01A83 rcr byte ptr [edi+5Eh],5Bh
}
I've compiled it in MS VS 2012.
What do all those extra lines mean, and why are they there? Why can't my _asm fragment just be used?
Can you tell us how you've compiled that function and how you got the disassembly?
When I compile using
cl /FAsc -c test.c
I get the following in the assembly listing for the inline assembler part:
; 4 : {
; 5 : _asm
0000a 53 push ebx
; 6 : {
; 7 : mov eax,[x];
0000b 8b 44 24 08 mov eax, DWORD PTR _x$[esp]
; 8 : mov ebx, [y];
0000f 8b 5c 24 0c mov ebx, DWORD PTR _y$[esp]
; 9 : mov [y],eax;
00013 89 44 24 0c mov DWORD PTR _y$[esp], eax
; 10 : mov [x], ebx;
00017 89 5c 24 08 mov DWORD PTR _x$[esp], ebx
; 4 : {
; 5 : _asm
0001b 5b pop ebx
$LN4#swap:
; 11 : }
One thing to note is that you aren't swapping what you'd really like to swap - your swapping the pointers that are passed to the function, not the items the pointers refer to. So when the function returns, the swapped data is thrown away. The function is just one big nop.
You might want to try somethign like:
_asm
{
mov eax,[x];
mov ebx,[y];
mov ecx, [eax]
mov edx, [ebx]
mov [eax], edx
mov [ebx], ecx
}
But frankly, performing the swap in C would likely result in similar (or better) code.
It's missing the first and last bytes. If you look at what the code is now:
inc ebp ; 45
or byte ptr [ebx],bh ; 08 3B
inc ebp ; 45
or al,74h ; 0C 74
or al,8Bh ; 0C 8B
inc ebp ; 45
or byte ptr [ebx+45890C5Dh],cl ; 08 8B 5D 0C 89 45
or al,89h ; 0C 89
pop ebp ; 5B
or byte ptr [ebx],dh ; 08 33
rcr byte ptr [edi+5Eh],5Bh ; C0 5F 5E 5B
If you ignore the first two bytes, you get this:
cmp eax, [ebp + 12] ; 3B 45 0C
jz skip ; 74 0C
mov eax, [ebx + 8] ; 8B 45 08
mov ebx, [ebp + 12] ; 8B 5D 0C
mov [ebp + 12], eax ; 89 45 0C
mov [ebx + 8], ebx ; 89 5B 08
skip:
xor eax, eax ; 33 C0
pop edi ; 5F
pop esi ; 5E
pop ebp ; 5B
It's missing the ret at the end, and, crucially, some instruction that has eax and [ebp + 8] as arguments (a mov would make sense there). The missing first byte desynchronized the disassembly with the instruction stream.
It's also missing the prologue, of course.
You need to push at the beginning and pop in the end if you want to see the end of main() :)
_asm
{
push eax //back-up of registers
push ebx
mov eax,[x];
mov ebx, [y];
mov [y],eax;
mov [x], ebx;
pop ebx //resume the registers where they were
pop eax // so, compiler can continue working normally
}
Because compiler uses them for other things too!
You could also have used xchg
mov eax,[x]
xchg eax, [y]
mov [x],eax
You 64 bit? Then there is a single read, single swap, single write. You can search it.
Good day!