Quantcast

Jump to content

» «
Photo

[REL|SRC] SA injector

6 replies to this topic
JGuntherS@NL
  • JGuntherS@NL

    Being a being

  • Members
  • Joined: 15 Nov 2005

#1

Posted 23 September 2007 - 02:38 PM

I've made a program that injects itself into the SA-proces, making it possible to manipulate San Andreas from within. The special thing about this program is that the CRT is also usable inside the SA-proces, so that you can use trivial functions like malloc and sprintf. It's written in C++, but with some adaptions, it can be made suitable for C as well. I hope someone can use this.

I used op9080's injector's source code for inspiration and I used some functions like findGTASA. Credits to him!

If you want to use it in your own project, you have to take into account that some compiler and linker settings are abnormal. These are:
  • Compiler: Runtime Library: Multi-threaded Debug (/MTd)
  • Compiler: Create/Use Precompiled Header: Not Using Precompiled Headers
  • Linker: Additional Dependencies: wbemuuid.lib
  • Linker: Entry Point: EntryPoint
  • Linker: Base Address: 0x48320000
  • Linker: Fixed Base Address: Generate a relocation section (/FIXED:NO)

And the download link: http://jesse.thorbit.../sainjector.zip

NOTE: You can resume SA's main thread by calling ResumeThread(dwSAThreadID), it's suspended when your main-function gets called.

SmokingCookie
  • SmokingCookie

    Snitch

  • Awaiting Authorisation
  • Joined: 19 May 2007

#2

Posted 23 September 2007 - 02:41 PM

You've already got 1 download biggrin.gif

JGuntherS@NL
  • JGuntherS@NL

    Being a being

  • Members
  • Joined: 15 Nov 2005

#3

Posted 25 September 2007 - 02:53 PM Edited by JGuntherS@NL, 25 September 2007 - 04:33 PM.

I have some more notes;

Next to CurWorkingDir's definition is a comment saying that it always has a backslash appended at the end. In fact, I made mistake, it doesn't have a backslash appended

The gta_sa.exe process quits if your RealMain function returns.

In the first part of the application (the 'loader' part, mostly the code in ExeInject.cpp and the first part of SA Injector.cpp), you can use some CRT-functions, like strcat. Others, like malloc, won't work, because CRT hasn't yet been initialised.

Edit: I've still got some new notes:

If you want to use some function from a non-standard DLL (like d3dx9.dll, it's not loaded by an application by default, in contrast to for example kernel32.dll or user32.dll. Of course it's loaded by SA, but that's because gta_sa.exe was linked to d3dx9.lib), you have to retrieve the module handle first by using GetModuleHandle, and then you retrieve the function's address by using GetProcAddress. Or, of course, if you're using a DLL that isn't loaded by gta_sa.exe, you have to load it yourself (LoadLibrary). Example:

CODE

// this is the equivalent of a function prototype, but we have to use this method now
typedef HRESULT (WINAPI *PD3DXCreateTextureFromFileInMemoryEx)(LPDIRECT3DDEVICE9,
 LPCVOID, UINT, UINT, UINT, UINT, DWORD, D3DFORMAT, D3DPOOL, DWORD, DWORD, D3DCOLOR,
 D3DXIMAGE_INFO *, PALETTEENTRY *, LPDIRECT3DTEXTURE9 *);

void SomeFunc()
{
 // first, get a handle to some d3dx9.dll, one of these should be loaded, but we don't know which
 // (depends on the DX version you've got), so we check them all
 hD3DX9 = GetModuleHandle("d3dx9_24.dll");
 if (!hD3DX9)
   hD3DX9 = GetModuleHandle("D3DX9_24.DLL");
 if (!hD3DX9)
   hD3DX9 = GetModuleHandle("d3dx9_25.dll");
 if (!hD3DX9)
   hD3DX9 = GetModuleHandle("D3DX9_25.DLL");
 if (!hD3DX9)
   hD3DX9 = GetModuleHandle("d3dx9_26.dll");
 if (!hD3DX9)
   hD3DX9 = GetModuleHandle("D3DX9_26.DLL");
 if (!hD3DX9)
   hD3DX9 = GetModuleHandle("d3dx9_27.dll");
 if (!hD3DX9)
   hD3DX9 = GetModuleHandle("D3DX9_27.DLL");
 if (!hD3DX9)
   hD3DX9 = GetModuleHandle("d3dx9_28.dll");
 if (!hD3DX9)
   hD3DX9 = GetModuleHandle("D3DX9_28.DLL");
 if (!hD3DX9)
   // HELP HELP HELP!
   return;

 pfunc = (PD3DXCreateTextureFromFileInMemoryEx) GetProcAddress(hD3DX9, "D3DXCreateTextureFromFileInMemoryEx");
 HRESULT hr = pfunc(argument, argument, .........);
}

ceedj
  • ceedj

    PEDS Creator

  • Members
  • Joined: 21 May 2005

#4

Posted 25 September 2007 - 06:02 PM

Congrats JGunther! smile.gif

Couple 'o questions:

1) Since it's based on the op9080 hook, does it use a DX SDK? If so which one?

2) I'm currently facing a problem trying to reload data because of the way it's injected. Example, I have this in my code:

CODE
void FileStuff()
{pFile = fopen("AnimKeys.txt","r");
fscanf (pFile, "%s %s", AnimIDA, AnimFileA);
fscanf (pFile, "%s %s", AnimIDB, AnimFileB);
fscanf (pFile, "%s %s", AnimIDC, AnimFileC);
fscanf (pFile, "%s %s", AnimIDD, AnimFileD);
fscanf (pFile, "%s %s", AnimIDE, AnimFileE);
fscanf (pFile, "%s %s", AnimIDF, AnimFileF);
fscanf (pFile, "%s %s", AnimIDG, AnimFileG);
fscanf (pFile, "%s %s", AnimIDH, AnimFileH);
fscanf (pFile, "%s %s", AnimIDI, AnimFileI);
fscanf (pFile, "%s %s", AnimIDJ, AnimFileJ);
fscanf (pFile, "%s %s", AnimIDK, AnimFileK);
fscanf (pFile, "%s %s", AnimIDL, AnimFileL);
fscanf (pFile, "%s %s", AnimIDM, AnimFileM);
fscanf (pFile, "%s %s", AnimIDN, AnimFileN);
fscanf (pFile, "%s %s", AnimIDO, AnimFileO);
fscanf (pFile, "%s %s", AnimIDP, AnimFileP);
fclose (pFile);


Which lets me use a text file to assign animations. The problem: I can't seem to reload anything without restarting the game; I suspect (though I am not nearly talented enough to confirm) that this is all "compiled" (for lack of a better term) at runtime - if I remove my text file, the game won't load at all. Any ideas how I might get around this without having to reload the game everytime?


JGuntherS@NL
  • JGuntherS@NL

    Being a being

  • Members
  • Joined: 15 Nov 2005

#5

Posted 25 September 2007 - 06:48 PM

1) It doesn't use a DX SDK, but you can implement it if you want (I've made a DXHook for it myself, so that does use a DX SDK)

2) I don't get your problem exactly. Do you mean it crashes if you call this function for the second time? (The first time you 'load', the second time you 'reload')

ceedj
  • ceedj

    PEDS Creator

  • Members
  • Joined: 21 May 2005

#6

Posted 25 September 2007 - 07:44 PM

QUOTE (JGuntherS@NL @ Sep 25 2007, 14:48)
2) I don't get your problem exactly. Do you mean it crashes if you call this function for the second time? (The first time you 'load', the second time you 'reload')

Yeah, without getting into real gory details, that function loads my text file at the start and assigns those animations to specific keys. Any attempts to "reload" inside the game causes a crash, which is why I suspect it's somewhat pre-compiled when I start the game from the desktop. The point is to allow users to ALT-TAB, change the text file, ALT-TAB back to the game a press a key to "reload" those animation names.

Sorry for derailing your thread; we can pick this up in PM if you like. smile.gif

JGuntherS@NL
  • JGuntherS@NL

    Being a being

  • Members
  • Joined: 15 Nov 2005

#7

Posted 25 September 2007 - 08:26 PM

I don't get a crash when I call your function twice (or even more times). I've made the following little debug-like program, can you tell me if it works for you? (Copy it into the SA Injector, but I think you can figure out the exact way yourself wink.gif )

CODE
char AnimIDA[10], AnimIDB[10], AnimIDC[10], AnimIDD[10], AnimIDE[10], AnimIDF[10],
AnimIDG[10], AnimIDH[10], AnimIDI[10], AnimIDJ[10], AnimIDK[10], AnimIDL[10],
AnimIDM[10], AnimIDN[10], AnimIDO[10], AnimIDP[10];

char AnimFileA[10], AnimFileB[10], AnimFileC[10], AnimFileD[10], AnimFileE[10], AnimFileF[10],
AnimFileG[10], AnimFileH[10], AnimFileI[10], AnimFileJ[10], AnimFileK[10], AnimFileL[10],
AnimFileM[10], AnimFileN[10], AnimFileO[10], AnimFileP[10];

void FileStuff()
{
FILE *pFile = fopen("C:\\AnimKeys.txt","r");
if (!pFile)
 return;
Beep(1000,100);
fscanf (pFile, "%s %s", AnimIDA, AnimFileA);
fscanf (pFile, "%s %s", AnimIDB, AnimFileB);
fscanf (pFile, "%s %s", AnimIDC, AnimFileC);
fscanf (pFile, "%s %s", AnimIDD, AnimFileD);
fscanf (pFile, "%s %s", AnimIDE, AnimFileE);
fscanf (pFile, "%s %s", AnimIDF, AnimFileF);
fscanf (pFile, "%s %s", AnimIDG, AnimFileG);
fscanf (pFile, "%s %s", AnimIDH, AnimFileH);
fscanf (pFile, "%s %s", AnimIDI, AnimFileI);
fscanf (pFile, "%s %s", AnimIDJ, AnimFileJ);
fscanf (pFile, "%s %s", AnimIDK, AnimFileK);
fscanf (pFile, "%s %s", AnimIDL, AnimFileL);
fscanf (pFile, "%s %s", AnimIDM, AnimFileM);
fscanf (pFile, "%s %s", AnimIDN, AnimFileN);
fscanf (pFile, "%s %s", AnimIDO, AnimFileO);
fscanf (pFile, "%s %s", AnimIDP, AnimFileP);
fclose (pFile);
}

int __stdcall RealMain()
{
ResumeThread(OpenThread(THREAD_ALL_ACCESS,FALSE,dwSAThreadID));
for (;;)
{
 Sleep(10);
 if(GetAsyncKeyState('S'))
 {
  FileStuff();
  MessageBox(NULL, AnimIDA, AnimFileA, MB_OK);
 }
}
return 0;
}


This works best if you start it and then Alt-Tab the SA window away, so it won't bother you and then press the S key. If it all works, a MessageBox should pop up, telling you the first entry in your file. Then modify the file and press S again. It should then pop up with the modified entries.

QUOTE
Sorry for derailing your thread; we can pick this up in PM if you like. smile.gif

No problem, there might be other people out there with the same or a similar problem, they might find this discussion useful smile.gif .




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users