MHS to DLL .. what's the error? (simple BF2 red-dot)

Need Help With an Existing Feature in Memory Hacking Software? Ask Here

Moderators: g3nuin3, SpeedWing, WhiteHat, mezzo

MHS to DLL .. what's the error? (simple BF2 red-dot)

Postby anacletou » Sun Sep 28, 2008 11:55 pm

I've got a small problem:

When I inject code by MHS the cheat it works.. but when I try to convert the code in a dll when I try to inject the game crashes everytime... what's my error? Thanks for help.




this is the "auto-assemble" code of mhs:

Alloc( MyCode, 2048 ) ; Allocate 2,048 bytes and store the allocated address into MyCode, which we use as the location where our new code goes.
Label( OverwrittenCode ) ; The code that was overwritten by the JMP to MyCode will go here.
Label( Exit ) ; JMP here to exit our custom code and go back to the original code.
Label( Return ) ; The location of the next instruction of the original code.
FullAccess( BF2.exe+0x0032D563, 2048 )
BF2.exe+0x0032D563 :
jmp MyCode
nop
nop
nop
nop
Return :
MyCode : ; The allocated address. Put your code after this.
OverwrittenCode : ; The overwritten code (code that was overwritten by the JMP to MyCode).
call dword ptr [eax+38]
mov dword ptr [edi+A0], 35
Exit : ; Automatic JMP back to the original code, or you can JMP Return directly to avoid coming here.
jmp Return

this is the CODE PREVIEW:

0072D563: JMP 042A0000
0072D568: NOP
0072D569: NOP
0072D56A: NOP
0072D56B: NOP

042A0000: CALL NEAR DWORD PTR [EAX+38]
042A0003: MOV DWORD PTR [EDI+A0], 35
042A000D: JMP 0072D56C

this is the trainer kit preview:

Poke 0072D563 E9 98 2A B7 03 90 90 90 90
Poke 042A0000 FF 50 38 C7 87 A0 00 00 00 35 00 00 00 E9 5A D5 48 FC


these are the bytes to write:

BYTE bInject0[] = { 0xE9, 0x98, 0x2A, 0xB7, 0x03, 0x90, 0x90, 0x90, 0x90, }; // 0x0072D563.
BYTE bInject1[] = { 0xFF, 0x50, 0x38, 0xC7, 0x87, 0xA0, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0xE9, 0x5A, 0xD5, 0x48, 0xFC, }; // 0x042A0000.

this is my dll. in c++ code:

// ultimamerda.cpp : Defines the initialization routines for the DLL.
//

#include "stdafx.h"
#include "ultimamerda.h"
#include "windows.h"
#include "tlhelp32.h"
#include "resource.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CultimamerdaApp

BEGIN_MESSAGE_MAP(CultimamerdaApp, CWinApp)
END_MESSAGE_MAP()


// CultimamerdaApp construction
HANDLE hand = 0;
bool OffsetInit = 0;

DWORD bf2Base = 0;
DWORD ThreadID;

LPVOID fica;
int pidBF2;
const BYTE Nop6Bytes[6] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
const BYTE Nop4Bytes[4] = {0x90, 0x90, 0x90, 0x90};
const BYTE Nop2Bytes[2] = {0x90, 0x90};

const BYTE redDOT1[9] = {0xE9, 0x98, 0x2A, 0xB7, 0x03, 0x90, 0x90, 0x90, 0x90};
const BYTE redDOT2[18] = {0xFF, 0x50, 0x38, 0xC7, 0x87, 0xA0, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0xE9, 0x5A, 0xD5, 0x48, 0xFC};

//Poke 0072D563 E9 98 2A B7 03 90 90 90 90
//Poke 042A0000 FF 50 38 C7 87 A0 00 00 00 35 00 00 00 E9 5A D5 48 FC

CultimamerdaApp::CultimamerdaApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}


// The one and only CultimamerdaApp object

CultimamerdaApp theApp;


// CultimamerdaApp initialization
DWORD WINAPI changeValue(LPVOID lParam) {
hand = GetCurrentProcess();
VirtualAllocEx(hand, (LPVOID)0x042A0000, 2048, MEM_COMMIT, PAGE_READWRITE);
::MessageBox(0, "memoria allocata", "memoria allocata", MB_ICONEXCLAMATION | MB_OK);
WriteProcessMemory(hand, (LPVOID)0x042A0000, &redDOT2, sizeof(redDOT2), 0);
WriteProcessMemory(hand, (LPVOID)0x0072D563, &redDOT1, sizeof(redDOT1), 0);
ExitThread(0);
}
BOOL CultimamerdaApp::InitInstance()
{

::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&changeValue, 0, 0, &ThreadID);

return TRUE;
}
anacletou
I Have A Few Questions
 
Posts: 4
Joined: Sun Sep 28, 2008 11:44 pm

Postby L. Spiro » Mon Sep 29, 2008 11:44 am

The Auto-Assembler script allocates a code cave and puts the code there.
If your DLL does not allocate a code cave it will crash.

Furthermore, if your DLL does allocate a code cave, the address of the allocation must be the same relative address as the one originally created by MHS.

The code cave made by MHS is 0x3B72A9D bytes from 0x0072D563 ({BASEADDRESS}). If the DLL changes location each time it is loaded you will have to allocate the address at {NEWBASEADDRESS}+ 0x3B72A9D.
Since you can not control the address returned by the allocation, you can not do this.

Therefore you can not simply copy the bytes into the program.
You need to adjust the offsets in the JMP values to account for the changing relative distance between the cave and the gateway.


L. Spiro
Our songs remind you of songs you’ve never heard.
User avatar
L. Spiro
L. Spiro
 
Posts: 3129
Joined: Mon Jul 17, 2006 10:14 pm
Location: Tokyo, Japan

Postby anacletou » Mon Sep 29, 2008 3:26 pm

Thanks a lot for the quick response :)

I've a doubt.. all the time that I inject the "autoassemble-code" MHS changes the address of the space allocated for the modified code (it reserves 2048 bytes) because I suppose that it reserves the space in at the first address free that it finds (for example 04B80000 or 04C80000 or 09D20000) and when I go to the deassembler the offsets are not inside "BF2.exe" but inside "All". So, what does it mean? It's not a code-cave inside the offset of the process but it seems that the code is outside..

P.S. I'm a little confused because I'm trying to learn the bases.
anacletou
I Have A Few Questions
 
Posts: 4
Joined: Sun Sep 28, 2008 11:44 pm

Postby L. Spiro » Mon Sep 29, 2008 4:05 pm

It can not be a memory address inside the module space of the game; that memory has already been allocated.
Windows® gives MHS the address, which will of course be on the heap (free space) not inside any module.
And it will indeed change every time.


L. Spiro
Our songs remind you of songs you’ve never heard.
User avatar
L. Spiro
L. Spiro
 
Posts: 3129
Joined: Mon Jul 17, 2006 10:14 pm
Location: Tokyo, Japan

Postby anacletou » Mon Sep 29, 2008 8:13 pm

OK now it works! I injected the asm code inside a free space in BF2.EXE handle (at this address 00816301).. so it's static and I've not problems to write bytes in memory. Thanks for the explanation!

But if I want use external code-cave like MHS do automatically (only to learn) what functions in C++ can I use to write in memory allocations? WriteProcessMemory only works with an handle and I don't know how to write bytes to a static offset outside of a process (without using a baseaddress + offset). I've already searched on google but I didn't found nothing that I can understand.

Thanks for all , MHS rocks!

p.s.
a good and simple guide to write asm code in c++ ?
anacletou
I Have A Few Questions
 
Posts: 4
Joined: Sun Sep 28, 2008 11:44 pm

Postby L. Spiro » Mon Sep 29, 2008 8:33 pm

#1: Research VirtualAllocEx().
#2: WriteProcessMemory() needs only the address where to write. There is nothing fancy about that.
#3: There is no simple way to write ASM in this context. You can use __asm in your own application but if you are trying to write ASM to be injected into another process you have to make your own assembler and it is not a simple task.


L. Spiro
Our songs remind you of songs you’ve never heard.
User avatar
L. Spiro
L. Spiro
 
Posts: 3129
Joined: Mon Jul 17, 2006 10:14 pm
Location: Tokyo, Japan

Postby jungletek » Tue May 12, 2009 7:04 am

So I know this is an old thread, but I thought I'd bump it because I have a relevant question:

So you're saying that using the Auto-Assembler, there's no way to specify where your codecave is allocated? It's always allocated outside of the process?
jungletek
I Have A Few Questions
 
Posts: 5
Joined: Thu May 07, 2009 1:25 am

Postby L. Spiro » Tue May 12, 2009 7:35 am

If you want to specify the address of the code cave use 0x0040EWHATEVER instead of an allocated label.


L. Spiro
Our songs remind you of songs you’ve never heard.
User avatar
L. Spiro
L. Spiro
 
Posts: 3129
Joined: Mon Jul 17, 2006 10:14 pm
Location: Tokyo, Japan

Postby jungletek » Tue May 12, 2009 1:21 pm

L. Spiro wrote:If you want to specify the address of the code cave use 0x0040EWHATEVER instead of an allocated label.


L. Spiro


Cheers, although I didn't see it listed in the helpfile, in the reference for the auto-assembler labels. Did I miss it? Perhaps it should be added, assuming it's not basic stuff that is assumed that most people should know.
jungletek
I Have A Few Questions
 
Posts: 5
Joined: Thu May 07, 2009 1:25 am

Postby L. Spiro » Tue May 12, 2009 6:44 pm

The help file explains labels:



Labels are used to indicate the addresses of instructions and end with a colon. Labels can be pure numeric literals (for example 01005224 :), numeric expressions (for example gamex86.dll+5224h), or identifiers created with the LABEL, GLOBALALLOC, or ALLOC commands (for example MyLabel :). Labels created with LABEL do not have addresses assigned to them. Instead, they are used to obtain the address of the next instruction (or data). Therefore, to specify an address for code, a numeric label or a label created with ALLOC must be used. If the first label in the code was created with LABEL, the code will be compiled at address 0x00000000 and is guaranteed to fail injection.



L. Spiro
Our songs remind you of songs you’ve never heard.
User avatar
L. Spiro
L. Spiro
 
Posts: 3129
Joined: Mon Jul 17, 2006 10:14 pm
Location: Tokyo, Japan


Return to Help

Who is online

Users browsing this forum: No registered users and 0 guests

cron