Difference between revisions of "Auto Assembler Example 3"

From Cheat Engine
Jump to navigation Jump to search
(Created page with '=== Creating A DLL === === Injecting the DLL ===')
 
m (LUA)
 
(7 intermediate revisions by 4 users not shown)
Line 1: Line 1:
 +
[[Category:Assembler]]
 
=== Creating A DLL ===
 
=== Creating A DLL ===
 +
In Visual Studio, click on "File->New Project" and select "Other Languages->Visual C++->Win32" and enter TestDLL as the project name.
  
=== Injecting the DLL ===
+
By default the project will be C++, which means the exported symbols will be mangled depending on argument types.  If you don't ''need'' C++, you can right-click on the project and pick Properties, then go to "Configuration Properties->C/C++->Advanced" and change the second option "Compile As" from "Default" to "Compile as C Code (/TC)".  Another option may be to use a block to tell it your externs are C, although I didn't get it injecting right:
 +
 
 +
<pre>
 +
extern "C" {
 +
__declspec(dllexport) int __stdcall myfunc(int a, int b)
 +
{
 +
return a * 2 + b;
 +
}
 +
 
 +
__declspec(dllexport) int myvalue = 9999;
 +
}
 +
</pre>
 +
 
 +
To export a function for use by your autoassembler or LUA script, decorate it with "__declspec(dllexport)"  If you want your functions to automatically take their arguments off the stack, use "__stdcall" as well (fnTestDll2):
 +
 
 +
<pre>
 +
#include "stdafx.h"
 +
 
 +
BOOL APIENTRY DllMain( HMODULE hModule,
 +
                      DWORD  ul_reason_for_call,
 +
                      LPVOID lpReserved
 +
)
 +
{
 +
switch (ul_reason_for_call)
 +
{
 +
case DLL_PROCESS_ATTACH:
 +
case DLL_THREAD_ATTACH:
 +
case DLL_THREAD_DETACH:
 +
case DLL_PROCESS_DETACH:
 +
break;
 +
}
 +
return TRUE;
 +
}
 +
 
 +
__declspec(dllexport) int nTestDll=9999;
 +
 
 +
__declspec(dllexport) int fnTestDll(int a, int b)
 +
{
 +
nTestDll++;
 +
return a * 2 + b;
 +
}
 +
 
 +
__declspec(dllexport) int __stdcall fnTestDll2(int a, int b)
 +
{
 +
nTestDll++;
 +
return a * 2 + b;
 +
}
 +
</pre>
 +
 
 +
=== Injecting The DLL ===
 +
==== Manual Injection ====
 +
From the Memory Viewer form, you can click on "Tools->Inject DLL" or hit CTRL+I.  This will allow you to select the DLL file and even call a function in the DLL.  This will register all exports, so from the disassembly you can right-click and say "Goto address" and enter "fnTestDll2" to go to that function.
 +
 
 +
==== Injecting in AutoAssembler ====
 +
You can use LOADLIBRARY, either passing the full path or just the DLL name (it will search in the same directory as your cheat table):
 +
<pre>
 +
loadlibrary(TestDll.dll)
 +
// or loadlibrary(C:\t\TestDll\debug\TestDll.dll)
 +
</pre>
 +
 
 +
==== LUA ====
 +
The injectDll(filename) function in LUA will also inject the DLL:
 +
<pre>
 +
injectDLL("TestDll.dll")
 +
</pre>
 +
 
 +
=== Calling From AutoAssembler ===
 +
 
 +
In your autoassembler script, use LOADLIBRARY to load a DLL and register its exported symbols.  You can then access its variables and call its functions like using any other symbol.  If you do not use __stdcall, you need to remove your arguments from the stack after the call.  Also you should realize that the arguments are pushed in reverse order.  This way functions that take variable number of arguments will always see the "first" argument at the top of the stack.
 +
 
 +
<pre>
 +
alloc(MyCode,512)
 +
label(MyData)
 +
loadlibrary(C:\t\TestDll\Debug\TestDll.dll)
 +
registersymbol(MyCode)
 +
registersymbol(MyData)
 +
 
 +
MyCode:
 +
push 3
 +
push 4
 +
call fnTestDll // fnTestDll(4, 3)
 +
add esp,8      // fnTestDll is not __stdcall so we need to remove arguments from stack
 +
mov [MyData], eax // result is returned in eax
 +
 
 +
push 24
 +
push 35
 +
call fnTestDll2 // fnTestDll2(35, 24)
 +
// fnTestDll2 is __stdcall so it will remove arguments from stack
 +
mov [MyData+4], eax // result is returned in eax
 +
 
 +
mov eax, [nTestDll] // exported global variable
 +
mov [MyData+8], eax
 +
ret
 +
 
 +
MyData:
 +
</pre>

Latest revision as of 14:56, 18 July 2020

Creating A DLL[edit]

In Visual Studio, click on "File->New Project" and select "Other Languages->Visual C++->Win32" and enter TestDLL as the project name.

By default the project will be C++, which means the exported symbols will be mangled depending on argument types. If you don't need C++, you can right-click on the project and pick Properties, then go to "Configuration Properties->C/C++->Advanced" and change the second option "Compile As" from "Default" to "Compile as C Code (/TC)". Another option may be to use a block to tell it your externs are C, although I didn't get it injecting right:

extern "C" {
	__declspec(dllexport) int __stdcall myfunc(int a, int b)
	{
		return a * 2 + b;
	}

	__declspec(dllexport) int myvalue = 9999;
}

To export a function for use by your autoassembler or LUA script, decorate it with "__declspec(dllexport)" If you want your functions to automatically take their arguments off the stack, use "__stdcall" as well (fnTestDll2):

#include "stdafx.h"

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

__declspec(dllexport) int nTestDll=9999;

__declspec(dllexport) int fnTestDll(int a, int b)
{
	nTestDll++;
	return a * 2 + b;
}

__declspec(dllexport) int __stdcall fnTestDll2(int a, int b)
{
	nTestDll++;
	return a * 2 + b;
}

Injecting The DLL[edit]

Manual Injection[edit]

From the Memory Viewer form, you can click on "Tools->Inject DLL" or hit CTRL+I. This will allow you to select the DLL file and even call a function in the DLL. This will register all exports, so from the disassembly you can right-click and say "Goto address" and enter "fnTestDll2" to go to that function.

Injecting in AutoAssembler[edit]

You can use LOADLIBRARY, either passing the full path or just the DLL name (it will search in the same directory as your cheat table):

loadlibrary(TestDll.dll)
// or loadlibrary(C:\t\TestDll\debug\TestDll.dll)

LUA[edit]

The injectDll(filename) function in LUA will also inject the DLL:

injectDLL("TestDll.dll")

Calling From AutoAssembler[edit]

In your autoassembler script, use LOADLIBRARY to load a DLL and register its exported symbols. You can then access its variables and call its functions like using any other symbol. If you do not use __stdcall, you need to remove your arguments from the stack after the call. Also you should realize that the arguments are pushed in reverse order. This way functions that take variable number of arguments will always see the "first" argument at the top of the stack.

alloc(MyCode,512)
label(MyData)
loadlibrary(C:\t\TestDll\Debug\TestDll.dll)
registersymbol(MyCode)
registersymbol(MyData)

MyCode:
push 3
push 4
call fnTestDll // fnTestDll(4, 3)
add esp,8      // fnTestDll is not __stdcall so we need to remove arguments from stack
mov [MyData], eax // result is returned in eax

push 24
push 35
call fnTestDll2 // fnTestDll2(35, 24)
// fnTestDll2 is __stdcall so it will remove arguments from stack
mov [MyData+4], eax // result is returned in eax

mov eax, [nTestDll] // exported global variable
mov [MyData+8], eax
ret

MyData: