 |
Cheat Engine The Official Site of Cheat Engine
|
| View previous topic :: View next topic |
| Author |
Message |
Pwnmanship Cheater
Reputation: 0
Joined: 19 Jan 2015 Posts: 25
|
Posted: Tue Mar 17, 2015 1:35 pm Post subject: C# - Hardware breakpoint not working properly |
|
|
In Binding of Isaac rebirth there is an address that accesses all the 'stones' in the room: E6ACE4
Now there are rooms with more than 31 stones like the room on the left with seed: 3476aawa (you can enter this when pressing 'tab' in the character select screen)
The script only finds 31 of the stones and the other 3 remain unfound. If I search them with Cheat Engine I do find them and there addresses have a different starting sequence. But they are still accessed by the same edx (E6ACE4). Now I think there is something wrong with the code below that won't let me find the addresses 'accessed' if they are not in the same sequence (look at UpdateTable(int cave, int offset)).
It would be awesome if somebody with more knowledge about memory reading can point me in the right direction or point out where the flaw in the code is.
Thanks in advance.
Update: I used a script that would inject code to get the edx value. This wasn't working properly so now I'm trying to set a hardware breakpoint, look a few posts below this one to see the code. The SetContext is working but the game crashes after setting the breakpoints.
Last edited by Pwnmanship on Thu Mar 19, 2015 1:54 pm; edited 3 times in total |
|
| Back to top |
|
 |
justa_dude Grandmaster Cheater
Reputation: 23
Joined: 29 Jun 2010 Posts: 893
|
Posted: Tue Mar 17, 2015 4:59 pm Post subject: |
|
|
I don't own the game and I'm not very interested in studying your code long enough to guess at errors (or even long enough to try to deduce the shellcode you're injecting, really), but have you tried debugging the game while using your trainer? Maybe something in the code cave you're injecting isn't assembling the way you expect or something. If, as you said, you can make the same cheat work in CE, then it should be easy to spot the difference.
_________________
A nagy kapu mellett, mindig van egy kis kapu.
----------------------
Come on... |
|
| Back to top |
|
 |
Pwnmanship Cheater
Reputation: 0
Joined: 19 Jan 2015 Posts: 25
|
Posted: Tue Mar 17, 2015 5:29 pm Post subject: |
|
|
| justa_dude wrote: | | I don't own the game and I'm not very interested in studying your code long enough to guess at errors (or even long enough to try to deduce the shellcode you're injecting, really), but have you tried debugging the game while using your trainer? Maybe something in the code cave you're injecting isn't assembling the way you expect or something. If, as you said, you can make the same cheat work in CE, then it should be easy to spot the difference. |
I'm not very skilled in making the cheats in CE, I only find the values in it. But the address in the edx I found accesses all the objects. As far as I know (the code isn't fully mine) the code injection is just to determine the edx value at an instrution that points to the objects.
If I look into all the 'stones' in the game with CE all those 'stones' are accessed by the same code. So in theory I would be able to find all the addresses it accesses but that doesn't seem to be the case. I'm pretty sure it's something in the code that doesn't do what is expected.
Update, the injected code:
| Code: | Before injecting:
isaac-ng.exe+BACE4 - 8B 43 20 - mov eax,[ebx+20]
isaac-ng.exe+BACE7 - 8B 49 0C - mov ecx,[ecx+0C]
After injecting:
isaac-ng.exe+BACE4 - E8 1F533C0E - call 0F230008
isaac-ng.exe+BACE9 - 90 - nop
And the code at 0F230008:
0F230000 - 08 20 - or [eax],ah
0F230002 - 65 0C 54 - or al,54
0F230005 - 00 00 - add [eax],al
0F230007 - 00 89 0D000023 - add [ecx+2300000D],cl
0F23000D - 0F8B 0D040023 - jnp 32230420
0F230013 - 0F89 993C0023 - jns 32233CB2
0F230019 - 0F83 F9787405 - jae 14977918
0F23001F - 83 C1 04 - add ecx,04
0F230022 - EB 05 - jmp 0F230029
0F230024 - B9 00000000 - mov ecx,00000000
0F230029 - 89 0D 0400230F - mov [0F230004],ecx
0F23002F - 8B 0D 0000230F - mov ecx,[0F230000] : [0C652008]
0F230035 - 8B 43 20 - mov eax,[ebx+20]
0F230038 - 8B 49 0C - mov ecx,[ecx+0C]
|
The 2nd line (al,54) keeps changing together with code below those lines.
As far as I know this makes sure I can get the ebx value of 8B4320.
But as I said I think the problem is not getting the edx or this injected code but the code that get's all the 'accessed' addresses.
|
|
| Back to top |
|
 |
justa_dude Grandmaster Cheater
Reputation: 23
Joined: 29 Jun 2010 Posts: 893
|
Posted: Tue Mar 17, 2015 6:29 pm Post subject: |
|
|
Start the game, enable your working CE script (the one you're trying to emulate), and record the injected code. Step through it with the debugger until you understand how it works. Then, disable the script, run your trainer, and again record the injected code (the listing you gave isn't disassembled correctly because you started at the wrong place - scroll up and down a bit and maybe it will get aligned properly or maybe not). Step through it with the debugger until you understand what is happening.
| Pwnmanship wrote: | | The 2nd line (al,54) keeps changing together with code below those lines. |
That makes sense, the script that you're copying probably reserves the first eight bytes for data storage - this would explain why the jump is to eight bytes after the allocated space. It would also explain why CE is getting confused while trying to disassemble that region.
_________________
A nagy kapu mellett, mindig van egy kis kapu.
----------------------
Come on... |
|
| Back to top |
|
 |
Pwnmanship Cheater
Reputation: 0
Joined: 19 Jan 2015 Posts: 25
|
Posted: Wed Mar 18, 2015 5:12 am Post subject: |
|
|
| justa_dude wrote: | Start the game, enable your working CE script (the one you're trying to emulate), and record the injected code. Step through it with the debugger until you understand how it works. Then, disable the script, run your trainer, and again record the injected code (the listing you gave isn't disassembled correctly because you started at the wrong place - scroll up and down a bit and maybe it will get aligned properly or maybe not). Step through it with the debugger until you understand what is happening.
| Pwnmanship wrote: | | The 2nd line (al,54) keeps changing together with code below those lines. |
That makes sense, the script that you're copying probably reserves the first eight bytes for data storage - this would explain why the jump is to eight bytes after the allocated space. It would also explain why CE is getting confused while trying to disassemble that region. |
I'll first try to make the script in CE than because I'm not trying to emulate a script I'm just trying to read the edx value at a certain address.
I tried doing that with breakpoints like you mentioned earlier but couldn't get it to work in C#. Posted it on stackoverflow http://stackoverflow.com/questions/28984286/read-edx-register but didn't receive much attention.
|
|
| Back to top |
|
 |
Dark Byte Site Admin
Reputation: 471
Joined: 09 May 2003 Posts: 25818 Location: The netherlands
|
Posted: Thu Mar 19, 2015 5:15 am Post subject: |
|
|
you need to watch for CREATE_THREAD_DEBUG_EVENT, which will provide you with the thread handles (there will be multiple)
and only when you have all the threads set the breakpoint (in every single thread)
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Like my help? Join me on Patreon so i can keep helping |
|
| Back to top |
|
 |
Pwnmanship Cheater
Reputation: 0
Joined: 19 Jan 2015 Posts: 25
|
Posted: Thu Mar 19, 2015 8:18 am Post subject: |
|
|
| Dark Byte wrote: | you need to watch for CREATE_THREAD_DEBUG_EVENT, which will provide you with the thread handles (there will be multiple)
and only when you have all the threads set the breakpoint (in every single thread) |
I did this and waited till I got all the threads. Than created the context again and did a SetThreadContext(); for every thread. But still not getting any EXCEPTION_DEBUG_EVENT with the right address afterwards.
There isn't alot of info on how to do this with C# and my lack of understanding at what I'm doing here isn't helping much either . I think I'll just create a Freelancer project for this code so I can move on.
Bedankt voor je hulp! (thanks for your help in dutch)
|
|
| Back to top |
|
 |
justa_dude Grandmaster Cheater
Reputation: 23
Joined: 29 Jun 2010 Posts: 893
|
Posted: Thu Mar 19, 2015 10:04 am Post subject: |
|
|
| Pwnmanship wrote: | | Than created the context again and did a SetThreadContext(); for every thread. But still not getting any EXCEPTION_DEBUG_EVENT with the right address afterwards. |
The reasons for this are readily apparent to anyone who has seen your question and answer on stackoverflow. The funniest bit is that you've already defined the flags for thread access you'll need to get the thread handle, even though you don't use them anywhere. You went to the copypasta buffet and ate your fill.
| Pwnmanship wrote: | | There isn't alot of info on how to do this with C# and my lack of understanding at what I'm doing here isn't helping much either :P. I think I'll just create a Freelancer project for this code so I can move on. |
At the risk of being disparaging, your lack of experience with C# is also hurting you. Aside from passing the wrong arguments to the get/set context functions (and failing to check return values), you've got a signed/unsigned mismatch that will probably prevent you from ever detecting a breakpoint should you manage to fix the first issue. If you can't interpret a compiler warning like, "useless comparison: signed/unsigned mismatch against out of range literal constant", then you're in for a long haul.
I'm not familiar with Freelancer, but if it's a way to pay someone to code a project for you then it's probably not a good idea. No offense, but you've already got plenty of access to code you don't understand. If it's just a learning exercise, then my advice is to learn to crawl before you try to walk. Don't try to incorporate a CE script into a C# trainer until you understand how the CE script works.
| Pwnmanship wrote: | | Bedankt voor je hulp! (thanks for your help in dutch) |
You, he thanks! Was it something I said? lol
_________________
A nagy kapu mellett, mindig van egy kis kapu.
----------------------
Come on... |
|
| Back to top |
|
 |
Pwnmanship Cheater
Reputation: 0
Joined: 19 Jan 2015 Posts: 25
|
Posted: Thu Mar 19, 2015 11:16 am Post subject: |
|
|
| justa_dude wrote: | | Pwnmanship wrote: | | Than created the context again and did a SetThreadContext(); for every thread. But still not getting any EXCEPTION_DEBUG_EVENT with the right address afterwards. |
The reasons for this are readily apparent to anyone who has seen your question and answer on stackoverflow. The funniest bit is that you've already defined the flags for thread access you'll need to get the thread handle, even though you don't use them anywhere. You went to the copypasta buffet and ate your fill.
| Pwnmanship wrote: | There isn't alot of info on how to do this with C# and my lack of understanding at what I'm doing here isn't helping much either . I think I'll just create a Freelancer project for this code so I can move on. |
At the risk of being disparaging, your lack of experience with C# is also hurting you. Aside from passing the wrong arguments to the get/set context functions (and failing to check return values), you've got a signed/unsigned mismatch that will probably prevent you from ever detecting a breakpoint should you manage to fix the first issue. If you can't interpret a compiler warning like, "useless comparison: signed/unsigned mismatch against out of range literal constant", then you're in for a long haul.
I'm not familiar with Freelancer, but if it's a way to pay someone to code a project for you then it's probably not a good idea. No offense, but you've already got plenty of access to code you don't understand. If it's just a learning exercise, then my advice is to learn to crawl before you try to walk. Don't try to incorporate a CE script into a C# trainer until you understand how the CE script works.
| Pwnmanship wrote: | | Bedankt voor je hulp! (thanks for your help in dutch) |
You, he thanks! Was it something I said? lol |
'your lack of experience with C# is also hurting you' this made no sense. I'm currently working as Lead Developer at a international ICT company you probably know. My lack of C++ and assembly is the problem here.
That is why I'm copying and not understanding what I'm doing. Anyway thanks for the insult.
Anyway, updated code:
| Code: | public static IntPtr GetEdx(IntPtr address, Process process)
{
const uint DBG_EXCEPTION_NOT_HANDLED = 0x80010001;
const uint EXCEPTION_SINGLE_STEP = 0x80000004;
const int DBG_CONTINUE = 0x00010002; // Seems to work better than DBG_EXCEPTION_NOT_HANDLED
//DebugSetProcessKillOnExit(0);
DEBUG_EVENT evt = new DEBUG_EVENT();
// Attach to the process we provided the thread as an argument
if (!DebugActiveProcess(process.Id))
throw new Win32Exception();
CONTEXT context = new CONTEXT();
foreach (ProcessThread thread in process.Threads)
{
uint iThreadId = (uint)thread.Id;
IntPtr hThread =
OpenThread(
ThreadAccessFlags.SUSPEND_RESUME | ThreadAccessFlags.SET_CONTEXT |
ThreadAccessFlags.GET_CONTEXT, false, iThreadId);
// Suspent the thread
if (SuspendThread(hThread) == -1) throw new ApplicationException("Cannot suspend thread.");
context = new CONTEXT
{
ContextFlags = (uint)CONTEXT_FLAGS.CONTEXT_DEBUG_REGISTERS |
(uint)CONTEXT_FLAGS.CONTEXT_INTEGER
};
// Get the context
if (!GetThreadContext(hThread, ref context))
throw new Win32Exception();
// Change the context
context.Dr0 = (uint)address;
context.Dr7 = 0x00000001;
// Set the changed context back
if (!SetThreadContext(hThread, ref context))
throw new Win32Exception();
// Check if setting the context give any errors
var error = Marshal.GetLastWin32Error();
if (error != 0)
{
throw new ApplicationException("Error is setting context.");
}
// Resume the thread
if (ResumeThread(hThread) == -1) throw new ApplicationException("Cannot resume thread.");
}
while (true)
{
if (!WaitForDebugEvent(out evt, -1))
throw new Win32Exception();
// Multiple if's for easier debugging at this moment
if (evt.dwDebugEventCode == (uint)DebugEventType.EXCEPTION_DEBUG_EVENT)
{
if (evt.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP)
{
if (evt.Exception.ExceptionRecord.ExceptionAddress == address)
{
context = new CONTEXT
{
ContextFlags = (uint)CONTEXT_FLAGS.CONTEXT_DEBUG_REGISTERS |
(uint)CONTEXT_FLAGS.CONTEXT_INTEGER
};
GetThreadContext((IntPtr)evt.dwThreadId, ref context);
return (IntPtr)context.Ebx; // ebx get
}
}
}
ContinueDebugEvent(evt.dwProcessId, evt.dwThreadId, DBG_CONTINUE);//DBG_EXCEPTION_NOT_HANDLED);
}
} |
Has no errors after SetThreadContext (with Masrhal.GetLastWin32Error()) but crashes the game. If somebody knows why the game is crashing or how to prevent this it would be great if you would share.
Edit: Maybe it has to do with the game? When I use CE's 'windows debugger' it also crashes, but not with the 'VEH debugger'.
Last edited by Pwnmanship on Thu Mar 19, 2015 4:02 pm; edited 1 time in total |
|
| Back to top |
|
 |
Dark Byte Site Admin
Reputation: 471
Joined: 09 May 2003 Posts: 25818 Location: The netherlands
|
Posted: Thu Mar 19, 2015 3:16 pm Post subject: |
|
|
for GetThreadContext to function you should set context.ContextFlags first as well.
Also, call SuspendThread before GetThreadContext, else the thread could potentially continue after GetThreadContext and suspendProcess, and do annoying things like acquiring a critical section (which setthreadcontext would not release)
but yeah, if it's steam then the windows debugger may not work. At least one of the threads is set to be hidden from the debugger, so when you set a breakpoint in that thread you'll crash.
3 options:
1: Try a non-steam version
2: change the loader so it doesn't enable that "do-not-track" flag
3: Go through hell and implement something similar like VEH debug.
(i'd go for 1)
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Like my help? Join me on Patreon so i can keep helping |
|
| Back to top |
|
 |
Pwnmanship Cheater
Reputation: 0
Joined: 19 Jan 2015 Posts: 25
|
Posted: Thu Mar 19, 2015 3:19 pm Post subject: |
|
|
| Dark Byte wrote: | for GetThreadContext to function you should set context.ContextFlags first as well.
Also, call SuspendThread before GetThreadContext, else the thread could potentially continue after GetThreadContext and suspendProcess, and do annoying things like acquiring a critical section (which setthreadcontext would not release)
but yeah, if it's steam then the windows debugger may not work. At least one of the threads is set to be hidden from the debugger, so when you set a breakpoint in that thread you'll crash.
3 options:
1: Try a non-steam version
2: change the loader so it doesn't enable that "do-not-track" flag
3: Go through hell and implement something similar like VEH debug.
(i'd go for 1) |
Thanks for your response. I had already put the suspend before the get because I thought the same thing. I'm just bought the humblestore version and will try it there.
Also: Setting the context flags before getting the context helped alot. The game keeps running now till I go to a room with 'stones' (which is what I was looking for). So I guess the debugger works at this moment but steam screws me.
Little update: If I debug all threads except for thread 0 the game doesn't crash. But also doesn't ever hit the breakpoint.
Second update: Seems like the humblestore Binding of Isaac Rebirth is also Steam only. So guess that only leaves option 2 or 3.
Third Update: Just found a way to do option 2: http://www.thehackerwithin.com/blog/11-08-07/Steam_s_anti-debugging_code.aspx
It's working, I get no crash and the 'evt.Exception.ExceptionRecord.ExceptionAddress == address' is true. The only thing is that after 'GetThreadContext' with evt.dwThreadId. The ebx in that context is still 0. Even if I first suspend the thread and create a new context with the 'CONTEXT_DEBUG_REGISTERS' and 'CONTEXT_INTEGER' flags.
Any idea why it would be 0?
Fourth Update: Got it working together with an edited version of this code: http://www.mpgh.net/forum/showthread.php?t=747257
This does however make all the 'stones' invisible. But I'll look into that.
Still no idea why mine doesn't work but i'll compare the two later.
Thanks alot for all the help guys!
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum
|
|