Difference between revisions of "Auto Assembler Example 3"
(Created page with '=== Creating A DLL === === Injecting the DLL ===') |
(→Creating A DLL) |
||
Line 1: | Line 1: | ||
=== 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. | ||
+ | |||
+ | 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> | ||
=== Injecting the DLL === | === Injecting the DLL === |
Revision as of 03:32, 12 December 2011
Contents
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.
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
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):
loadlibrary(TestDll.dll) // or loadlibrary(C:\t\TestDll\debug\TestDll.dll)
LUA
The injectDll(filename) function in LUA will also inject the DLL:
injectDll("TestDll.dll")
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.
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: