Click here to Skip to main content
15,867,453 members
Articles / Programming Languages / Objective C

Stealing Program's Memory

Rate me:
Please Sign up or sign in to vote.
4.79/5 (75 votes)
2 Dec 20032 min read 350.3K   4K   114   82
An advanced article on allocating and using memory in another process using the Win32 API.

Introduction

I was recently trying to steal strings from another program's listview control. You need to pass a pointer so it knows where to put the string. Normally, this wouldn't be a problem, but because Windows uses virtual memory, pointers are not valid across programs.

Virtual memory is how Windows deals out memory to all its programs. It makes programs think they have 2 Gb of memory to use. It also protects programs from using each other's memory so if one program crashes, it doesn't take down the whole system with it.

So after coding a fair bit, I realized my pointers were all invalid and it wouldn't work. A few hours of digging through MSDN brought me to the functions VirtualAllocEx(), VirtualFreeEx(), WriteProcessMemory() and ReadProcessMemory(). Armed with this new information, I set out to modify my code. Here is what I had so far:

#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <windows.h>
#include <commctrl.h>

int main(void) {
 /* Run through the windows until we find our listview. */
 HWND hwnd=FindWindow(NULL, "Stealing Program's Memory: ListView");
 HWND listview=FindWindowEx(hwnd, NULL, "SysListView32", NULL);

 int count=(int)SendMessage(listview, LVM_GETITEMCOUNT, 0, 0);
 int i;

 char item[512], subitem[512];

 /* Shove all items of listview into item and subitem
    and print out one by one. */

 LVITEM lvi;
 lvi.cchTextMax=512;

 for(i=0; i<count; i++) {
  lvi.iSubItem=0;
  lvi.pszText=item;
  SendMessage(listview, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)&lvi);

  lvi.iSubItem=1;
  lvi.pszText=subitem;
  SendMessage(listview, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)&lvi);

  printf("%s - %s\n", item, subitem);
 }
 return 0;
}

As I said before, this won't work. The pointers to lvi, item, and subitem all get screwed when they go across process. The solution? Use WriteProcessMemory() and ReadProcessMemory() to use the other programs memory, perform LVM_GETITEMTEXT on it, and read it back. Hackish yes, but then again reading items from another program's listview control is one giant hack.

First, we get the process of the listview like this:

unsigned long pid;
HANDLE process;
GetWindowThreadProcessId(listview, &pid);
process=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ|
                    PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION, FALSE, pid);

Next, we create three pointers, LVITEM *_lvi, char *_item, and char *_subitem and allocate them in the other program's virtual memory space with VirtualAllocEx():

LVITEM *_lvi=(LVITEM*)VirtualAllocEx(process, NULL, sizeof(LVITEM),
                                     MEM_COMMIT, PAGE_READWRITE);
char *_item=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
                                  PAGE_READWRITE);
char *_subitem=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
                                     PAGE_READWRITE);

Now, we point lvi.pszText to _item, and copy its memory to _lvi using WriteMemoryProcess():

lvi.pszText=_item;
WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);

Now that we have an LVITEM pointer that is valid in the other programs virtual memory, we can shoot off LVM_GETITEMTEXT to listview and copy _item's text into item so we can read it in our program:

SendMessage(hwnd, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);
ReadProcessMemory(process, _item, item, max, NULL);

Repeat that for subitem, then free the memory we used in the other program's memory:

VirtualFreeEx(process, _lvi, 0, MEM_RELEASE);
VirtualFreeEx(process, _item, 0, MEM_RELEASE);
VirtualFreeEx(process, _subitem, 0, MEM_RELEASE);

Yay, all done. In case that didn't make too much sense to you, here is our new code, all fixed up:

#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <windows.h>
#include <commctrl.h>

int main(void) {
 HWND hwnd=FindWindow(NULL, "Stealing Program's Memory: ListView");
 HWND listview=FindWindowEx(hwnd, NULL, "SysListView32", NULL);

 int count=(int)SendMessage(listview, LVM_GETITEMCOUNT, 0, 0);
 int i;

 LVITEM lvi, *_lvi;
 char item[512], subitem[512];
 char *_item, *_subitem;
 unsigned long pid;
 HANDLE process;

 GetWindowThreadProcessId(listview, &pid);
 process=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ|
                     PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION, FALSE, pid);

 _lvi=(LVITEM*)VirtualAllocEx(process, NULL, sizeof(LVITEM),
                              MEM_COMMIT, PAGE_READWRITE);
 _item=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
                             PAGE_READWRITE);
 _subitem=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
                                PAGE_READWRITE);

 lvi.cchTextMax=512;

 for(i=0; i<count; i++) {
  lvi.iSubItem=0;
  lvi.pszText=_item;
  WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
  SendMessage(listview, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);

  lvi.iSubItem=1;
  lvi.pszText=_subitem;
  WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
  SendMessage(listview, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);

  ReadProcessMemory(process, _item, item, 512, NULL);
  ReadProcessMemory(process, _subitem, subitem, 512, NULL);

  printf("%s - %s\n", item, subitem);
 }

 VirtualFreeEx(process, _lvi, 0, MEM_RELEASE);
 VirtualFreeEx(process, _item, 0, MEM_RELEASE);
 VirtualFreeEx(process, _subitem, 0, MEM_RELEASE);

 return 0;
}

If you're looking to use a program's memory for another reason, or have had a similar problem to mine, adapting this should be fairly easy.

This article was originally written for int64.org.

License

This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below. A list of licenses authors might use can be found here.


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
jinfd2-Sep-21 8:59
jinfd2-Sep-21 8:59 
Suggestionyou must assign the LVITEM with the same bit-pattern as listview's host process's target platform (x86 / x64). Pin
jinfd2-Sep-21 3:07
jinfd2-Sep-21 3:07 
QuestionGetting the images Pin
prashanth008418-Sep-19 21:15
prashanth008418-Sep-19 21:15 
AnswerRe: Getting the images Pin
jinfd2-Sep-21 8:50
jinfd2-Sep-21 8:50 
SuggestionGetting Image Index in Addition to Item Text Pin
Andrei Cuñada11-Oct-15 23:26
Andrei Cuñada11-Oct-15 23:26 
QuestionI tried to read Header control? using HDITEM . Pin
SathishMask29-Sep-14 5:36
SathishMask29-Sep-14 5:36 
Questionthanks Pin
Imbue16-Mar-13 10:37
Imbue16-Mar-13 10:37 
Thanks a million. This is exactly what I needed!
QuestionLVM_GETITEMRECT Pin
Zockerman™22-May-12 7:08
Zockerman™22-May-12 7:08 
AnswerRe: LVM_GETITEMRECT Pin
prashanth008418-Sep-19 22:46
prashanth008418-Sep-19 22:46 
GeneralMy vote of 5 Pin
Synetech2-Mar-12 14:08
Synetech2-Mar-12 14:08 
QuestionBut GetWindowText() works. :-? Pin
Synetech2-Mar-12 11:51
Synetech2-Mar-12 11:51 
QuestionRemove Item Pin
Mustafa Chelik11-Dec-11 2:38
Mustafa Chelik11-Dec-11 2:38 
QuestionC# Code Version Pin
Nilesh bhope8-Aug-11 2:57
Nilesh bhope8-Aug-11 2:57 
AnswerRe: C# Code Version Pin
taylorza21-Aug-11 1:23
professionaltaylorza21-Aug-11 1:23 
GeneralRe: C# Code Version Pin
Nilesh bhope29-Aug-11 2:01
Nilesh bhope29-Aug-11 2:01 
GeneralRe: C# Code Version Pin
Nilesh bhope29-Aug-11 5:04
Nilesh bhope29-Aug-11 5:04 
GeneralThank you very much - it is exactly what I needed. Pin
__stas__15-Nov-10 22:37
__stas__15-Nov-10 22:37 
GeneralExcellent article though requires a little addition Pin
Member 373653224-Jul-09 4:22
Member 373653224-Jul-09 4:22 
GeneralRe: Excellent article though requires a little addition Pin
Member 71363228-Apr-10 5:49
Member 71363228-Apr-10 5:49 
Generala problem about List Control Pin
dyj682213-Jul-09 18:01
dyj682213-Jul-09 18:01 
GeneralDoes the job Pin
software_chotmail13-Jun-09 13:42
software_chotmail13-Jun-09 13:42 
GeneralAPI is returning blank for LVM_GETITEMTEXT message in 64 bit system (Win2003). Pin
Joshi, Rushikesh6-Apr-09 0:50
professionalJoshi, Rushikesh6-Apr-09 0:50 
QuestionRe: API is returning blank for LVM_GETITEMTEXT message in 64 bit system (Win2003). Pin
anadipsia12-Aug-09 3:21
anadipsia12-Aug-09 3:21 
AnswerRe: API is returning blank for LVM_GETITEMTEXT message in 64 bit system (Win2003). Pin
ChewsHumans11-Mar-10 14:36
ChewsHumans11-Mar-10 14:36 
Questioncode returns blanks when tried on listview which seems to be with window style LVS_OWNERDRAWFIXED Pin
Member 436362620-Jan-09 0:05
Member 436362620-Jan-09 0:05 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.