View previous topic :: View next topic |
Author |
Message |
dlpb Advanced Cheater Reputation: 0
Joined: 11 Dec 2013 Posts: 71
|
Posted: Mon Jan 09, 2017 10:22 am Post subject: Which to use: WriteProcessMemory or MoveMemory |
|
|
At the moment, I am using MoveMemory in my DLL. It does what I need, but I see other people using
WriteProcessMemory(GetCurrentProcess, Proc, @Value, SizeOf(Value), n);
It seems to change memory without requiring VirtualProtect. But is this safe, or am I just better sticking to MoveMemory with virtualprotect?
|
|
Back to top |
|
|
STN I post too much Reputation: 42
Joined: 09 Nov 2005 Posts: 2672
|
Posted: Mon Jan 09, 2017 11:37 am Post subject: |
|
|
Neither, you are inside the memory space already write directly to it. People using WPM inside a dll either don't understand they can just access the memory or don't care about the unnecessary calls they're making.
WPM does call NTVirtualProtect inside its implementation. MoveMemory does write kind of directly but why even call that when you can directly do manipulation.
_________________
|
|
Back to top |
|
|
dlpb Advanced Cheater Reputation: 0
Joined: 11 Dec 2013 Posts: 71
|
Posted: Mon Jan 09, 2017 12:10 pm Post subject: |
|
|
Thanks. That's a great idea and I think I know what you mean. This is my new function example:
Code: | procedure WriteInteger (Address: Pointer; Value: Integer);
var
OldProtection : DWORD;
Begin
if VirtualProtect(Address,4,PAGE_EXECUTE_READWRITE, @oldprotection) then
begin
pinteger(Address)^ := Value;
VirtualProtect(Address, 4, oldprotection, @oldprotection);
FlushInstructionCache(0, Address, 4);
end;
End; |
Can you see anything there that would lead to an issue? Does Oldprotection need to be defined differently on a 64 bit system for example?
And a simple hook proc:
Code: | procedure HookProc(OrigFunc: LongWord; MyFunc: Pointer);
var
OldProtection : DWORD;
begin
if VirtualProtect(Pointer (OrigFunc), 5, PAGE_EXECUTE_READWRITE, @oldprotection) then
begin
pByte( Pointer(OrigFunc) )^:= $E9;
pLongInt( Pointer(OrigFunc + 1) )^:= PAnsiChar(MyFunc) - PAnsiChar(OrigFunc) - 5;
VirtualProtect(Pointer (OrigFunc), 5, oldprotection, @oldprotection);
FlushInstructionCache(0, Pointer(OrigFunc), 5);
end;
end; |
|
|
Back to top |
|
|
STN I post too much Reputation: 42
Joined: 09 Nov 2005 Posts: 2672
|
Posted: Mon Jan 09, 2017 1:20 pm Post subject: |
|
|
I am not that good in delphi but it looks fine to me, you can compile in 64bit and easily fix any errors that might pop up.
DWORD should be fine as it just holds the protection flags/values. You can use NativeInt/NativeUInt and delphi/lazarus should take care of the var size depending on the platform you're compiling it for.
I actually wrote the dll in masm so i could pretty much copy-paste game's asm code and used the trainer as injector (c++).
_________________
|
|
Back to top |
|
|
dlpb Advanced Cheater Reputation: 0
Joined: 11 Dec 2013 Posts: 71
|
Posted: Mon Jan 09, 2017 1:26 pm Post subject: |
|
|
Looks like "Pointer" is a signed 32 bit value (so my LongWord above is pointless... no pun intended). I guess since I am only writing this for an x86 program, it doesn't need to be anything else. As long as it will work the same in 32 and 64 bit, it's ok by me.
|
|
Back to top |
|
|
atom0s Moderator Reputation: 198
Joined: 25 Jan 2006 Posts: 8517 Location: 127.0.0.1
|
Posted: Tue Jan 10, 2017 12:32 am Post subject: |
|
|
Keep in mind that when you are randomly just applying VirtualProtect changes to pages of memory, that often times you will 'corrupt' the page list and expand things further than expected. ie. Make a dump of the memory page list before you make any changes, do your changes, then redump and compare. You'll notice that often times the restored page information is not the same as before.
This is a pretty easy way for games to keep track of memory allocates and changes by third-party applications and detect your edits, if an anti-cheat is involved. Just something to keep in mind.
_________________
- Retired. |
|
Back to top |
|
|
dlpb Advanced Cheater Reputation: 0
Joined: 11 Dec 2013 Posts: 71
|
Posted: Tue Jan 10, 2017 5:25 pm Post subject: |
|
|
Hmmm.... Not sure what you mean? You got an example of how I would do this in delphi to be on the safe side.
I just assumed that it restored the correct permissions and that was it.
|
|
Back to top |
|
|
atom0s Moderator Reputation: 198
Joined: 25 Jan 2006 Posts: 8517 Location: 127.0.0.1
|
Posted: Tue Jan 10, 2017 5:53 pm Post subject: |
|
|
dlpb wrote: | Hmmm.... Not sure what you mean? You got an example of how I would do this in delphi to be on the safe side.
I just assumed that it restored the correct permissions and that was it. |
I don't use Delphi, sorry.
_________________
- Retired. |
|
Back to top |
|
|
dlpb Advanced Cheater Reputation: 0
Joined: 11 Dec 2013 Posts: 71
|
Posted: Tue Jan 10, 2017 6:37 pm Post subject: |
|
|
Since this is mostly api stuff, how is it done in C?
|
|
Back to top |
|
|
atom0s Moderator Reputation: 198
Joined: 25 Jan 2006 Posts: 8517 Location: 127.0.0.1
|
Posted: Tue Jan 10, 2017 7:25 pm Post subject: |
|
|
dlpb wrote: | Since this is mostly api stuff, how is it done in C? |
You can query for the page information via:
- VirtualQuery or VirtualQueryEx (depending on if you are injected or not.)
- You can determine the page(s) that will be affected with this information.
- Alter the page(s) that you will need to affect via VirtualProtect or VirtualProtectEx (depending on if you are injected or not.)
- Restore the page information afterward that was affected based on the previous data you queried for.
From an old project of mine that is open source, I demonstrated this via:
Code: |
HRESULT _memcpy_vec( LPVOID lpDest, const LPVOID lpSource, int nSize )
{
std::vector< MEMORY_BASIC_INFORMATION > m_vMemInformation;
BYTE* btCurrentPage = reinterpret_cast< BYTE* >( lpDest );
while( btCurrentPage < ( reinterpret_cast< BYTE* >( lpDest ) + nSize ) )
{
MEMORY_BASIC_INFORMATION mbi = { 0 };
if( VirtualQuery( reinterpret_cast< LPVOID >( btCurrentPage ), &mbi, sizeof( mbi ) ) )
m_vMemInformation.push_back( mbi );
btCurrentPage = ( reinterpret_cast< BYTE* >( mbi.BaseAddress ) + mbi.RegionSize );
}
DWORD dwOldProtect = 0;
for( int x = 0; x < static_cast< int >( m_vMemInformation.size() ); x++ )
VirtualProtect( m_vMemInformation[x].BaseAddress, m_vMemInformation[x].RegionSize, PAGE_READWRITE, &dwOldProtect );
memcpy( lpDest, lpSource, nSize );
for( int x = 0; x < static_cast< int >( m_vMemInformation.size() ); x++ )
VirtualProtect( m_vMemInformation[x].BaseAddress, m_vMemInformation[x].RegionSize, m_vMemInformation[x].Protect, &dwOldProtect );
return S_OK;
} |
My newer methods are closed source, sorry. I do not share much code publicly anymore due to all the rippers these days.
_________________
- Retired. |
|
Back to top |
|
|
|