-1

my problem is the following. I have 2 functions, one that calls WriteProcessMemory and returns it's result and another that sends the buffer to the first one.

If i send a static variable as the buffer from the 2nd to the 1st no problem, but vice-versa it crashes.

Here's the source for the 1st:

void WriteMem(LPVOID addr, LPCVOID *buffer,size_t size){

int i = WriteProcessMemory(hProc, addr, buffer, size, NULL);

    if(i)
        printf("Success\n");
    else
        printf("Fail\n");

}

Source for the 2nd:

Segmentation fault:

void EditCards(BYTE victim){

BYTE cardsDrawn = 23;
puts("Choose the cards:");
scanf("%hhu",&cardsDrawn);

if(cardsDrawn > 40)
    cardsDrawn = 40;

cardsDrawn = 40 - cardsDrawn;//If the enemy has 5 cards then 45 have been drawn :P

WriteMem( victim ? Y_ENEMY_CARDS : Y_PLAYER_CARDS, &cardsDrawn, sizeof(BYTE));



}

Works fine:

void EditCards(BYTE victim){

static BYTE cardsDrawn = 23;
puts("Choose the cards:");
scanf("%hhu",&cardsDrawn);

if(cardsDrawn > 40)
    cardsDrawn = 40;

cardsDrawn = 40 - cardsDrawn;//If the enemy has 5 cards then 45 have been drawn :P

WriteMem( victim ? Y_ENEMY_CARDS : Y_PLAYER_CARDS, &cardsDrawn, sizeof(BYTE));



}

The space alocated for cardsDrawn afaik is still allocated when passed to next WriteMem why fail?

EDIT: No i'm editing the memory of another process. If you want to know it's ePSXe.exe

hProc is a global variable assigned in the main function. It's an handle for the process i'm editing its memory.

Here's what is requested:

#define Y_PLAYER_CARDS ((LPVOID)0x0B76510)
#define Y_ENEMY_CARDS (LPVOID)(Y_PLAYER_CARDS + 0x20)
krystalgamer
  • 146
  • 12
  • It this all running in the same process? If so you probably don't need (and shouldn't be using) WriteProcessMemory. If the code is running in different processes, could you provide more information about that? – jimhark Sep 01 '15 at 23:46
  • 4
    Where are `Y_ENEMY_CARDS` and `Y_PLAYER_CARDS` defined, and what are their values? Where is `hProc` being assigned. Please consider the advice at [mcve] – theB Sep 01 '15 at 23:47
  • @HarryJohnston But it's `"%hhu"` which specifies an `unsigned char`. – user3386109 Sep 02 '15 at 00:03
  • @theB Those 2 are being defined in an header file. – krystalgamer Sep 02 '15 at 00:09
  • @jimhark Different proccess. – krystalgamer Sep 02 '15 at 00:09
  • @HarryJohnston Yes, thanks for pointing out! :D – krystalgamer Sep 02 '15 at 00:10
  • @krystalgamer, I see what you are saying. What does GetLastError return after WriteProcessMemory fails? And what version of Windows are you running on? – jimhark Sep 02 '15 at 00:37
  • @user3386109: not according to the [Visual Studio documentation](https://msdn.microsoft.com/en-us/library/xdb9w69d.aspx), so far as I can see. Do you have a reference? – Harry Johnston Sep 02 '15 at 00:41
  • @krystalgamer, when you say "it crashes" do you mean your process that's calling WriteProcessMemory, or the "victim" process? – jimhark Sep 02 '15 at 00:44
  • @user3386109: in Visual Studio 2010, `%hhu` actually writes 4 bytes. I guess the invalid extra `h` make it ignore the prefix altogether. – Harry Johnston Sep 02 '15 at 00:45
  • 1
    It doesn't matter for your problem, but why is `WriteMem()`'s prototype `void WriteMem(LPVOID addr, LPCVOID *buffer,size_t size)` instead of `void WriteMem(LPVOID addr, LPCVOID buffer,size_t size)`? You're passing in (and using) a pointer to a buffer, not a pointer-to-a-pointer. It's confusing/misleading if nothing else. – Michael Burr Sep 02 '15 at 01:53
  • @HarryJohnston I suppose this is a little late, but my reference was the C11 draft specification section 7.21.6.2 (which describes `fscanf`) paragraph 11 (which lists the length modifiers). Not sure if Microsoft intends to support C11. – user3386109 Sep 02 '15 at 03:30
  • @user3386109: I believe not, but they are trying to keep C++ up to date; luckily, the latest C++ standard also contains the `hh` prefix. Michael (in the comments to my answer) reports that Visual Studio 2015 does include support for `hh`, even though it isn't in the documentation. – Harry Johnston Sep 02 '15 at 20:54
  • Better duplicate: http://stackoverflow.com/questions/15825254/why-is-scanfhhu-char-overwriting-other-variables-when-they-are-local – Harry Johnston Sep 02 '15 at 20:56

2 Answers2

1

I was able to reproduce your problem with a simplified version of your code; it still crashes even if WriteMem() does nothing! Here's the problem:

scanf("%hhu",&cardsDrawn);

The hh prefix is valid in Linux but is not supported in the Microsoft C runtime.

Instead, use

{
  int x; 
  scanf("%u",&x);
  cardsdrawn = x;
}
Harry Johnston
  • 35,639
  • 6
  • 68
  • 158
  • Note that Visual C++ 2015 (aka MSVC 14) supports the `hh` prefix, even though it's not documented (yet). – Michael Burr Sep 02 '15 at 07:31
  • Here's my tests , if i use `%hc` i don't get segmentation fault but i have another problem. The result is key-code not the number. Looks like i need to stick with `static` – krystalgamer Sep 02 '15 at 10:47
  • 1
    @krystalgamer: With the `static` 'solution' you're relying on the undefined behavior not having a noticeable effect - it's still a memory corruption bug, just one that you're not seeing a problem with. Yet. Why not perform the `scanf()` into an `unsigned int`, then covert that to a byte that gets copied using `WriteMem()`?: `unsigned int x = 0; scanf("%u",&x); cardsDrawn = x;`. Now there's no memory corruption. – Michael Burr Sep 02 '15 at 17:18
0

The problem is that you're identifying the address to write in the other process using a pointer in your own process. Windows uses a virtual memory system, so addresses are local to the process, and the fact that your process has an object located at a particular address doesn't tell you anything about where the objects are located in some other process.

"Trainers" (Programs that manipulate internal data structures of other programs, often games) solve this in several ways:

  • Globals and static variables often have consistent addresses across multiple runs of a program, and allow you to construct a table (map) of their addresses.

  • Dynamic objects get new addresses every time a program runs, so a trainer typically uses a pattern search to find an object, or reads pointers in global variables of the other program, to locate the current address for that object.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720