Externalist Posted November 26, 2006 Posted November 26, 2006 (edited) First of all, sorry for my poor english since it's not my first language , but I'll try my best to make the content understandable. I was making a simple program that would read another process's memory Via the most popular FindWindow -> GetWindowThreadProcessId -> OpenProcess -> ReadProcessMemory method and all worked fine while assembling insinde WinAsm IDE and running "inside" the IDE. But once I started to run the program outside the IDA, in other words when I double clicked on the produced .exe then the program wouldn't function as expected so I went on debugging the program in OllyDbg to find out which API failed. But the strange thing is, even in OllyDbg, if I press the RUN button the program would run exactly the way it was supposed to(and even read the right values from memory thus, no API failing) but after closing Olly and running the program indepently through double clicking it, it fails again. So I assumed the program which I want to read memory from uses some Anti-Readmemory tricks and indeed, after a little testing I found out that the OpenProcess API returns False. So my question is, is there any other way to read another process's memory other than the above method? I've searched & looked at other people's code but over 70% use the same method and the other 30% use a programming language I have no knowledge in . Thanks in advance. Edited November 26, 2006 by scmmaker
Guest Pickled Posted November 27, 2006 Posted November 27, 2006 (edited) Yes of course!One of the most popular methods is called DLL Injection whereby you can directly access the contents of image you have hooked.For example: In the .exe you are hooking, say you want to read data from the location 0x400123 which is say a game of some sorts, 0x400123 = NumberOfLives.You could inject a dll and create a new thread which scans that process./*Search google for DLL injection, it's very straighforward You can trick windows into loading your DLL into the image of another app,then create a new thread which you can then utilise to play inside the other process directly.See basic outline example below for hacking a game of some sort :)*/BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason, LPVOID lpvReserved){ switch (fdwReason) { case DLL_PROCESS_ATTACH: /* When the DLL is injected, this code is called, which creates a new Thread which then calls back to your Function (MyThreadProc) (callback) */ CreateThread(MyThreadProc, ... /*see MSDN for CreateThread*/); break; case DLL_PROCESS_DETACH: break; } return TRUE;}DWORD WINAPI MyThreadProc(LPVOID lParam){ //Read the contents of lives in our application int* NumberOfLives = (int*)NumberOfLives; //Display Results printf("NumberOfLives left: %d\n", *NumberOfLives); /* Now do Whatever you like here in your own thread with direct access to the process!! No more need for Read/WriteProcessMemory! Use DIRECT access! :) If you need to write new opcodes etc. then use VirtualProtect(/*see MSDN*/PAGE_EXECUTE_READWRITE...) to disable page security attributes for the specified region */ return 0;} Edited November 27, 2006 by Pickled
cektop Posted November 27, 2006 Posted November 27, 2006 It's been a veeery long time since I've written something like that but it sounds to me like some exceptions are going on of which you didn't take care. When you open an application in debugger, it catches exceptions and decides if it should handle them itself or pass them to program.It would be good if you can paste that specific piece of code where you open/attach to process and read from it.
Externalist Posted November 28, 2006 Author Posted November 28, 2006 dll injection indeed! Until now, I did practicly everything I can like trying to change the token privilege or the process privilege reading the MSDN debugging reference but since I'm so much of a newbie, soon enough I ran into a deadend. I must read those dll injection documents and get this over with! Thanks for the advice. and as for the code, there really is nothing in there. only this Readmem procinvoke FindWindow, NULL, addr ProgNamemov windhand,eaxinvoke GetWindowThreadProcessId, windhand, addr pidinvoke OpenProcess,PROCESS_VM_READ, 0, pidmov phandle,eaxinvoke ReadProcessMemory,phandle, ReadStart, addr Buffer, 20, NULLReadmem Endp and in the DlgProc, a wsprintf for conversion, SetDlgItemText to output the result and that's all there is. I don't know why the program's behaving that way but all I could guess is because the SE_DEBUG_PRIVILEGE flag for the process(or process token?) is disabled(which was enabled when the program was run through the debugger/assembler IDE). If only there was a way to enable it...
cektop Posted November 28, 2006 Posted November 28, 2006 It might not be necessary to turn on debug privileges. You should try to VirtualProtectEx that area of memory before reading.
Externalist Posted November 28, 2006 Author Posted November 28, 2006 (edited) Still... Win32.hlp says VirtualProtectEx needs a handle that has PROCESS_VM_OPRATION access but when I try to open the process with OpenProcess API passing PROCESS_VM_OPERATION flag, It would simply fail to open the process. I just wonder how on earth the debugger/IDE sets their privileges to highest. If only there was a way to imitate the same routine, then everything would be solved... but that just a theory. Thanks for the help. Edited November 28, 2006 by scmmaker
Guest fl3a Posted December 1, 2006 Posted December 1, 2006 If You loke read only virtual memory of other processes You don't need set SeDebugPrivilege. Only if You need open process like system service (winlogon, ...) You'll need this privilege. This is example try to get process handle by pid and then read data from process PEB block. By calling VirtualProtect You can change page privileges from Read, Execute to CopyWrite or CopyWriteExecute. /* Adjusting Process Token Privileges */ if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) { fprintf(stderr, "OpenProcessToken - GetLastError: 0x%.8d\n", GetLastError()); return 1; } if(!LookupPrivilegavalue("", SE_DEBUG_NAME, &luidDebug)) { fprintf(stderr, "LookupPrivilegavalue - GetLastError: 0x%.8d\n", GetLastError()); return 1; } tok.PrivilegeCount = 1; tok.Privileges[0].Luid = luidDebug; tok.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if(!AdjustTokenPrivileges(hToken, FALSE, &tok, sizeof(tok), NULL, NULL)) { fprintf(stderr, "AdjustTokenPrivileges - GetLastError: 0x%.8d\n", GetLastError()); return 1; } InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); for(ProcessId=1; ProcessId<4095; ProcessId++) { if(!(ProcessId % 4)) { ClientId.UniqueThread = 0; ClientId.UniqueProcess = (HANDLE)ProcessId; NtStatus = NtOpenProcess( &ProcessHandle, PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, &ObjectAttributes, &ClientId); if(!NtStatus) { printf("%.2d PID: %.4d ", i, ProcessId); hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ProcessId); if(!hProcess) printf("State: H "); else printf("State: - "); i++; NtStatus = NtQueryInformationProcess( ProcessHandle, 0, (PVOID) &ProcessInformation, sizeof(PROCESS_BASIC_INFORMATION), &ReturnLength); if(NtStatus) { fprintf(stderr, "NtQueryInformationProcess - NtStatus: 0x%.8X\n", NtStatus); return 1; } NtStatus = NtReadVirtualMemory( ProcessHandle, ProcessInformation.PebBaseAddress, &Peb, sizeof(Peb), &dwSize);...
Externalist Posted December 2, 2006 Author Posted December 2, 2006 (edited) Wow, that is absolutely awesome!!! That might be just the answer I was looking for! I would have never been able to figure that out with MSDN Debugging Reference, seeing that there are some undocumented NTDLL functions and for my lack of knowledge... I wish I could try that out right away but the army makes it hard to let me use my freetime on things I really want to do... Anyway, thanks a bunch for helping me out! But I still have a few questions about some places that confuses me; First of all, under the if(!NtStatus), I see a variable 'i' where I can't find anywhere. Where is it coming from? And the for(ProcessId=1; ProcessId<4095; ProcessId++) loop, because of my lack of knowledge I don't know why it has to perform the routine for 4096 Processes and moreover, the processes that has an ID number dividible by 4? Just a side question, but if I could get the process's (which I want to read memory) ID, then can I omit the for loop? Thanks in advance! Edited December 2, 2006 by scmmaker
Guest fl3a Posted December 2, 2006 Posted December 2, 2006 (edited) Hi scmmaker These undocumented functions are native version of well-known functions exported by kernel32.dll. For example NtReadVirtualMemory is native version of ReadProcessMemory. Native functions don't have body like other functions. They use int 2eh or sysenter (syscall) to jump to kernel mode. I used it because my program look for all running processes. But many of trojan horses hook kernel32 and ntdll exports like WriteProcessMemory, OpenProcess, NtQuerySystemInformation, ... So I called native functions directly: _declspec(naked)NTSTATUS NTAPI NtQueryInformationProcess( IN PHANDLE ProcessHandle, IN PROCESSINFOCLASS ProcessInformationClass, OUT PVOID ProcessInformation, IN ULONG ProcessInformationLength, OUT PULONG ReturnLength OPTIONAL){ __asm { mov eax, 0x86 lea edx, [esp+0x04] int 0x2E ret 0x14 }} It works only on Windows 2k SP2! 'i' was just counter for listed processes. Look at Your task manager... All processes has pids which can divide by 4! 4095 it was max number of pid. But I'm not sure this is true. If You like read more about undocumented functions look for book "Native API" by Gary Nebbett. This is link to complete source code: http://vixen03.info/fl3a/ProcId.rar pass: lot5ProcId7 // how to call native api in Asm xor edx, edx push edx ; EaLength push edx ; EaBuffer push 60h ; CreateOptions push edx ; CreateDisposition push edx ; ShareAccess push edx ; FileAttributes push edx ; AllocationSize push edx ; IoStatusBlock push edi ; ObjectAttributes push 40100000h ; DesiredAccess lea eax, handle push eax ; FileHandle mov eax, 20h lea edx, [esp] int 2eh add esp, 2ch // And description of NtCreateFile: http://undocumented.ntinternals.net/UserMo...CreateFile.html Edited December 2, 2006 by fl3a
Externalist Posted December 2, 2006 Author Posted December 2, 2006 Wow, I never knew native functions would be that simple... and I thought they were something huge and never even bothered to look into them! That's very new stuff(at least for me), thanks for the info! And finally I made a success! and I never knew it would be that simple. Couldn't have done it without you. I thank you very much for all the help/advice you gave me and hope you have a very pleasant day!
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now