flat assembler
Message board for the users of flat assembler.

Index > Windows > [Solved] My memory patch to current process is not working

Goto page 1, 2  Next
Author
Thread Post new topic Reply to topic
uu



Joined: 20 Jul 2024
Posts: 44
uu 08 Sep 2024, 12:54
I try to learn hacking by trying WriteProcessMemory, but a simpler one, to its own process with all access rights.

The code below shows empty message box twice. The second message box should have popped up text string with "1234" as caption and "12345678" as message. But it is not working.

Does anybody know why?

EDIT on Sept 11, 2024: A final working version:

Code:
format PE GUI at 0x400000
entry start

include 'win32a.inc'

section '.data' data readable writeable

  message rb 8+1
  caption rb 4+1
  buffer db '12345678',0,'1234',0
  len = $ - buffer

section '.text' code readable executable

  start:

        invoke  MessageBox,HWND_DESKTOP,message,caption,0
        invoke  GetCurrentProcess
        invoke  WriteProcessMemory, eax, 0x401000, buffer, len, 0
        or      eax, eax
        jz      exit
        invoke  MessageBox,HWND_DESKTOP,message,caption,0
 exit:
        invoke  ExitProcess,0

section '.idata' import data readable

  library kernel,'KERNEL32.DLL',\
          user,'USER32.DLL'

  import kernel,\
         ExitProcess,'ExitProcess', \
         GetCurrentProcess, 'GetCurrentProcess', \
         WriteProcessMemory, 'WriteProcessMemory'

  import user,\
         MessageBox,'MessageBoxA'
    


Last edited by uu on 12 Sep 2024, 10:24; edited 2 times in total
Post 08 Sep 2024, 12:54
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20632
Location: In your JS exploiting you and your system
revolution 08 Sep 2024, 13:03
You need to have a security token to use "dangerous" APIs like that.

Check out the APIs OpenProcessToken, LookupPrivilegeValue, AdjustTokenPrivileges for some details.
Post 08 Sep 2024, 13:03
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20632
Location: In your JS exploiting you and your system
revolution 08 Sep 2024, 13:13
BTW: The errno value can tell you what went wrong.

Returned by GetLastError
Post 08 Sep 2024, 13:13
View user's profile Send private message Visit poster's website Reply with quote
uu



Joined: 20 Jul 2024
Posts: 44
uu 08 Sep 2024, 13:18
revolution wrote:
BTW: The errno value can tell you what went wrong.

Returned by GetLastError


Thanks for your replies, the WriteProcessMemory returns non-zero value, which means no error....
Post 08 Sep 2024, 13:18
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20632
Location: In your JS exploiting you and your system
revolution 08 Sep 2024, 13:23
Okay, then my mistake. But you still need PROCESS_VM_WRITE and PROCESS_VM_OPERATION privilege on the handle else nothing will happen.
Post 08 Sep 2024, 13:23
View user's profile Send private message Visit poster's website Reply with quote
uu



Joined: 20 Jul 2024
Posts: 44
uu 08 Sep 2024, 13:31
From what I checked, GetCurrentProcess returns handle which has the PROCESS_ALL_ACCESS access right (All possible access rights for a process object).

PROCESS_VM_WRITE is 0x20, and PROCESS_VM_OPERATION is 0x08, but PROCESS_ALL_ACCESS is 0xFFFF...

But maybe my understanding of the process object and privilege is wrong.
Post 08 Sep 2024, 13:31
View user's profile Send private message Reply with quote
uu



Joined: 20 Jul 2024
Posts: 44
uu 08 Sep 2024, 13:44
(This thread made me feel like a cyber criminal, but maybe I overthink)
Post 08 Sep 2024, 13:44
View user's profile Send private message Reply with quote
uu



Joined: 20 Jul 2024
Posts: 44
uu 08 Sep 2024, 14:24
I run it in debugger, and interestingly, the "12345678..." is copied to address 0x40100E, not 0x401000.....

Any ideas?


Description: After WriteProcessMemory, data section 0x40100E changed / overlapped with buffer
Filesize: 14.53 KB
Viewed: 3732 Time(s)

2.PNG


Description: Before WriteProcessMemory, data section 0x401000
Filesize: 14.72 KB
Viewed: 3732 Time(s)

1.PNG


Post 08 Sep 2024, 14:24
View user's profile Send private message Reply with quote
uu



Joined: 20 Jul 2024
Posts: 44
uu 08 Sep 2024, 14:29
Replace this line to will work:
Code:
        invoke  WriteProcessMemory, eax, message, buffer, len, 0       


I misunderstand "the pointer to the base address"....
Quote:
[in] lpBaseAddress

A pointer to the base address in the specified process to which data is written.
Post 08 Sep 2024, 14:29
View user's profile Send private message Reply with quote
Ali.Z



Joined: 08 Jan 2018
Posts: 820
Ali.Z 08 Sep 2024, 21:15
revolution wrote:
You need to have a security token to use "dangerous" APIs like that.

Check out the APIs OpenProcessToken, LookupPrivilegeValue, AdjustTokenPrivileges for some details.


not needed for processes having same security level, which is default for vast majority of windows apps.

_________________
Asm For Wise Humans
Post 08 Sep 2024, 21:15
View user's profile Send private message Reply with quote
Ali.Z



Joined: 08 Jan 2018
Posts: 820
Ali.Z 08 Sep 2024, 21:22
uu wrote:
(This thread made me feel like a cyber criminal, but maybe I overthink)

your example is kinda useless and have no point.

you can learn from my example of hacking minesweeper and creating ESP hack along with dll injector and modifying game data internally.

https://board.flatassembler.net/topic.php?t=21714

_________________
Asm For Wise Humans
Post 08 Sep 2024, 21:22
View user's profile Send private message Reply with quote
uu



Joined: 20 Jul 2024
Posts: 44
uu 09 Sep 2024, 05:48
Ali.Z wrote:
uu wrote:
(This thread made me feel like a cyber criminal, but maybe I overthink)

your example is kinda useless and have no point.

you can learn from my example of hacking minesweeper and creating ESP hack along with dll injector and modifying game data internally.

https://board.flatassembler.net/topic.php?t=21714


Your use of WriteProcessMemory is truly advanced!!! Surprised
Post 09 Sep 2024, 05:48
View user's profile Send private message Reply with quote
uu



Joined: 20 Jul 2024
Posts: 44
uu 11 Sep 2024, 09:55
uu wrote:
Replace this line to will work:
Code:
        invoke  WriteProcessMemory, eax, message, buffer, len, 0       


I misunderstand "the pointer to the base address"....
Quote:
[in] lpBaseAddress

A pointer to the base address in the specified process to which data is written.


This line also works, so now I can point to any writeable memory space in current process, not necessary point to variable (in this case "message").

Code:
invoke  WriteProcessMemory, eax, 0x401000, buffer, len, 0    
Post 11 Sep 2024, 09:55
View user's profile Send private message Reply with quote
uu



Joined: 20 Jul 2024
Posts: 44
uu 11 Sep 2024, 10:00
Actually I want to test WriteProcessMemory to another running program, I already got the C++ code from StackOverflow, but maybe later.

Code:
call [FindWindow]
call [GetWindowThreadProcessId]
call [OpenProcess]
call [ReadProcessMemory]
call [WriteProcessMemory]
    
Post 11 Sep 2024, 10:00
View user's profile Send private message Reply with quote
uu



Joined: 20 Jul 2024
Posts: 44
uu 11 Sep 2024, 20:57
hackmem.asm (can be any filename):
Code:
format PE GUI
entry start

include 'win32a.inc'

section '.data' data readable writeable

_message        db      "---You've been hacked--- ",0
_len            =       $ - _message
;_name           db      "Command Prompt - console",0
_name           db      "gui",0
_id             dd      ?
_text           db      "Memory patched successfully",0
_caption        db      "hackmem",0
_error_1        db      "Error finding window.",0
_error_2        db      "Error getting process ID.",0
_error_3        db      "Error opening process.",0
_error_4        db      "Error writing memory.",0

section '.code' code readable executable

start:
        push    _name
        push    0
        call    [FindWindow]
        or      eax, eax
        jz      .error_1
        push    _id
        push    eax
        call    [GetWindowThreadProcessId]
        or      eax, eax
        jz      .error_2
        push    [_id]
        push    -1
        push    PROCESS_ALL_ACCESS
        call    [OpenProcess]
        or      eax, eax
        jz      .error_3
        push    0
        push    _len
        push    _message
        push    0x401000
        push    eax
        call    [WriteProcessMemory]
        or      eax, eax
        jz      .error_4
        push    0
        push    _caption
        push    _text
        push    HWND_DESKTOP
        call    [MessageBox]
        jmp     .exit

.error_1:
        push    MB_ICONERROR
        push    _caption
        push    _error_1
        push    HWND_DESKTOP
        call    [MessageBox]
        jmp     .exit

.error_2:
        push    MB_ICONERROR
        push    _caption
        push    _error_2
        push    HWND_DESKTOP
        call    [MessageBox]
        jmp     .exit

.error_3:
        push    MB_ICONERROR
        push    _caption
        push    _error_3
        push    HWND_DESKTOP
        call    [MessageBox]
        jmp     .exit

.error_4:
        push    MB_ICONERROR
        push    _caption
        push    _error_4
        push    HWND_DESKTOP
        call    [MessageBox]
        jmp     .exit

.exit:
        push    0
        call    [ExitProcess]

section '.idata' import readable writable

 library kernel32, 'KERNEL32.DLL',\
         user32,'USER32.DLL'

 import kernel32,\
        OpenProcess, 'OpenProcess', \
        WriteProcessMemory, 'WriteProcessMemory', \
        ExitProcess,'ExitProcess'

 import user32,\
        FindWindow, 'FindWindowA', \
        GetWindowThreadProcessId, 'GetWindowThreadProcessId', \
        MessageBox, 'MessageBoxA'

    


gui.asm
Code:
format PE GUI at 0x400000
entry start

include 'win32a.inc'

section '.data' data readable writeable

_text           db      "This is a secret message.",0
_caption        db      "gui",0

section '.code' code readable executable

start:
        push    MB_ICONINFORMATION + MB_RETRYCANCEL
        push    _caption
        push    _text
        push    HWND_DESKTOP
        call    [MessageBox]
        cmp     eax, IDCANCEL
        jz      .exit
        jmp     start

.exit:
        push    0
        call    [ExitProcess]

section '.idata' import readable writable

 library kernel32, 'KERNEL32.DLL',\
         user32,'USER32.DLL'

 import kernel32,\
        ExitProcess,'ExitProcess'

 import user32,\
        MessageBox, 'MessageBoxA'

    


How to play:
1. Run gui.exe
2. Click Retry to repeat, or Cancel to quit, but don't click Cancel yet.
3. Run hackmem.exe
4. Now click Retry in gui.exe to see "new" message
5. Have fun!


Description: This is the original message box in gui.exe
Filesize: 4.5 KB
Viewed: 3410 Time(s)

1.PNG


Description: Run hackmem.exe while keep clicking Retry on gui.exe
Filesize: 12.71 KB
Viewed: 3410 Time(s)

2.PNG


Post 11 Sep 2024, 20:57
View user's profile Send private message Reply with quote
uu



Joined: 20 Jul 2024
Posts: 44
uu 12 Sep 2024, 07:48
This is another one, not message box, but a console app.

The code is similar to hackmem.asm above, just change the path to the console.EXE, that's all.

You need to change the "_name" variable to the window name of "console.EXE", or else it won't work.
Code:
_name           db      "C:\Users\User\Projects\console.EXE",0    


hackmem2.asm
Code:
format PE GUI
entry start

include 'win32a.inc'

section '.data' data readable writeable

_message        db      "---You've been hacked--- ",13,10,13,10
_len            =       $ - _message
_name           db      "C:\Users\User\Projects\console.EXE",0
_id             dd      ?
_text           db      "Memory patched successfully.",0
_caption        db      "hackmem",0

section '.code' code readable executable

start:
        push    _name
        push    0
        call    [FindWindow]
        or      eax, eax
        jz      .exit
        push    _id
        push    eax
        call    [GetWindowThreadProcessId]
        or      eax, eax
        jz      .exit
        push    [_id]
        push    -1
        push    PROCESS_ALL_ACCESS
        call    [OpenProcess]
        or      eax, eax
        jz      .exit
        push    0
        push    _len
        push    _message
        push    0x401000
        push    eax
        call    [WriteProcessMemory]
        or      eax, eax
        jz      .exit
        push    0
        push    _caption
        push    _text
        push    HWND_DESKTOP
        call    [MessageBox]

.exit:
        push    0
        call    [ExitProcess]

section '.idata' import readable writable

 library kernel32, 'KERNEL32.DLL',\
         user32,'USER32.DLL'

 import kernel32,\
        OpenProcess, 'OpenProcess', \
        WriteProcessMemory, 'WriteProcessMemory', \
        ExitProcess,'ExitProcess'

 import user32,\
        FindWindow, 'FindWindowA', \
        GetWindowThreadProcessId, 'GetWindowThreadProcessId', \
        MessageBox, 'MessageBoxA'

    


You'll need to compile console.asm and launch console.EXE by double clicking it in Windows Explorer (don't type and run it in an existing Command Prompt window).
Then run hackmem2.exe to see the changing of text string.

console.ASM
Code:
format PE console at 0x400000
entry start

include 'win32a.inc'

section '.data' data readable writeable

_message        db      "This is a secret message... Press Esc to quit",13,10,13,10
_len            =       $ - _message
_console        dd      ?

section '.code' code readable executable

start:
        push    STD_OUTPUT_HANDLE
        call    [GetStdHandle]
        mov     dword [_console], eax

.play:
        push    200
        call    [Sleep]
        push    0
        push    0
        push    _len
        push    _message
        push    dword [_console]
        call    [WriteConsole]
        push    0x1B
        call    [GetKeyState]
        bt      eax, 15
        jc      .exit
        jmp     .play

.exit:
        push    0
        call    [ExitProcess]

section '.idata' import readable

 library kernel32, 'KERNEL32.DLL',\
         user32,'USER32.DLL'

 import kernel32,\
        GetStdHandle, 'GetStdHandle', \
        WriteConsole, 'WriteConsoleA', \
        Sleep, 'Sleep', \
        ExitProcess,'ExitProcess'

 import user32,\
        GetKeyState, 'GetKeyState'    


Description:
Filesize: 265.33 KB
Viewed: 3338 Time(s)

2024-09-12.gif


Description: Memory patch to console app in action!
Filesize: 54.27 KB
Viewed: 3367 Time(s)

3.png




Last edited by uu on 12 Sep 2024, 11:35; edited 1 time in total
Post 12 Sep 2024, 07:48
View user's profile Send private message Reply with quote
Ali.Z



Joined: 08 Jan 2018
Posts: 820
Ali.Z 12 Sep 2024, 11:15
keep in mind that you can run into multiple issues when finding a window by its caption, providing class name for certain apps might be the only way to get their hwnd. (not 100% reliable under all Windows versions for all type of gui apps, this is what i experienced in past)

a better solution exist, either EnumWindows or EnumDesktopWindows, it also allow you to define your own filtering rules.

_________________
Asm For Wise Humans
Post 12 Sep 2024, 11:15
View user's profile Send private message Reply with quote
uu



Joined: 20 Jul 2024
Posts: 44
uu 12 Sep 2024, 12:13
Ali.Z wrote:
keep in mind that you can run into multiple issues when finding a window by its caption, providing class name for certain apps might be the only way to get their hwnd. (not 100% reliable under all Windows versions for all type of gui apps, this is what i experienced in past)

a better solution exist, either EnumWindows or EnumDesktopWindows, it also allow you to define your own filtering rules.


Thanks, I will remember this.
Post 12 Sep 2024, 12:13
View user's profile Send private message Reply with quote
Mat-Quasar



Joined: 02 Mar 2025
Posts: 82
Mat-Quasar 31 Mar 2025, 15:32
uu wrote:

How to play:
1. Run gui.exe
2. Click Retry to repeat, or Cancel to quit, but don't click Cancel yet.
3. Run hackmem.exe
4. Now click Retry in gui.exe to see "new" message
5. Have fun!


Forgot to mention at the time I publish the code, if the destination (data section) is not writeable, then "hackmem.exe" will fail.
Please see screenshot.


Description:
Filesize: 38.28 KB
Viewed: 1077 Time(s)

hackmem_failed.PNG


Post 31 Mar 2025, 15:32
View user's profile Send private message Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 1151
Location: Russia
macomics 31 Mar 2025, 15:51
Mat-Quasar wrote:
Forgot to mention at the time I publish the code, if the destination (data section) is not writeable, then "hackmem.exe" will fail.
It is enough to use VirtualProtect before and after writing.
Post 31 Mar 2025, 15:51
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2  Next

< Last Thread | Next Thread >
Forum Rules:
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


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.