Click here to Skip to main content
Click here to Skip to main content

Stealing Program's Memory

By , 2 Dec 2003
 

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 it's 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 it's 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

About the Author

Cory Nelson
Web Developer
United States United States
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Questionthanks PinmemberImbue16 Mar '13 - 10:37 
QuestionLVM_GETITEMRECT PinmemberZockerman™22 May '12 - 7:08 
GeneralMy vote of 5 PinmemberSynetech2 Mar '12 - 14:08 
QuestionBut GetWindowText() works. :-? PinmemberSynetech2 Mar '12 - 11:51 
QuestionRemove Item PinmemberMustafa Chelik11 Dec '11 - 2:38 
QuestionC# Code Version PinmemberNilesh bhope8 Aug '11 - 2:57 
GeneralThank you very much - it is exactly what I needed. Pinmember__stas__15 Nov '10 - 22:37 
GeneralExcellent article though requires a little addition PinmemberMember 373653224 Jul '09 - 4:22 
Generala problem about List Control Pinmemberdyj682213 Jul '09 - 18:01 
GeneralDoes the job Pinmembersoftware_chotmail13 Jun '09 - 13:42 
GeneralAPI is returning blank for LVM_GETITEMTEXT message in 64 bit system (Win2003). Pinmemberrushijoshi6 Apr '09 - 0:50 
Questioncode returns blanks when tried on listview which seems to be with window style LVS_OWNERDRAWFIXED PinmemberMember 436362620 Jan '09 - 0:05 
GeneralRidiculous... Pinmemberkilt6 Nov '08 - 3:11 
QuestionHow to steal TStringGrid's Memory? Pinmemberwhite88815 Aug '08 - 17:31 
GeneralVery good!!! PinmemberKlaus Hattinger12 Aug '08 - 6:59 
GeneralDoesn't work in Vista 64 Pinmemberblurmotion17 May '08 - 2:18 
GeneralVirtualAllocEx problems PinmemberCedar8217 Nov '07 - 4:45 
GeneralStatic Text Pinmemberjosip cagalj23 Aug '07 - 1:14 
QuestionGetting list vew Data with sendmessage(xxxxx) PinmemberXzion28 Mar '07 - 21:40 
Questionwhat if not window default control Pinmember9999kkk25 Nov '06 - 0:04 
GeneralA Clever Utility, and an Explanation of Cross-Process Copying of Data PinmemberMike O'Neill6 Sep '06 - 16:14 
GeneralC# Version PinmemberMarco225028 Aug '06 - 15:57 
JokeThanks a lot! This is exactly what I'm looking for. Pinmembersongkiet9 Aug '06 - 8:58 
Questionretrieve text on statusbar Pinmemberdoenoe31 Jul '06 - 22:22 
QuestionGet strings from Microsoft Outlook SUPERGRID Pinmemberkopyt19 Jul '06 - 2:13 
QuestionPossible to do same for delphi TStringGrid? PinmemberAbsorbant Pad13 Jun '06 - 0:10 
Questioncan we write text? Pinmemberaldo hexosa4 Mar '06 - 2:47 
Questionleak? Pinmember[cs2]27 Jan '06 - 7:11 
GeneralProblem with one App Pinmemberclivet18 Sep '05 - 0:50 
GeneralSelect and SetText PinmemberJ3ff28 Jul '05 - 10:30 
Generala PinsussAnonymous9 Dec '04 - 9:57 
QuestionControl Propterties? Pinmemberriezebosch19 Oct '04 - 4:39 
Generalhere is another crude way Pinmemberblairburnham@yahoo.com3 Oct '04 - 9:03 
GeneralAwesome!!! - Here's a mod to get data from all columns Pinmemberjjohnston30 Jan '04 - 17:46 
Generalexcellent Pinmemberarkyc29 Jan '04 - 17:57 
GeneralThanks Pinmemberfsmith23 Dec '03 - 23:31 
QuestionCan you overwrite it? PinsussAnonymous16 Dec '03 - 3:29 
QuestionWhat if there are 2 list controls in that window? Pinmembermelwyn11 Dec '03 - 23:35 
Generalis it the &quot;fourth&quot; way.... Pinmemberowais9 Dec '03 - 19:25 
GeneralType-o PinmemberDavidCrow9 Dec '03 - 2:50 
QuestionCould you fix the horizontal scrolling annoyance? PinmemberWREY3 Dec '03 - 10:31 
Generalcool hack PinmemberGurvinder Singh3 Dec '03 - 10:25 

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

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 3 Dec 2003
Article Copyright 2003 by Cory Nelson
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid