简体   繁体   中英

Write/Read a memory-protected process's memory

I'll try to explain my problem the best I can.
I'm trying to access to a memory-protected process memory (Minesweeper).
I'll put my code first and then I'll explain what's the thing I want to archieve. (If you read everything and know another way to do this, please post it).

First, the getProcessHandle, a function that returns a open handle to the process with name procName.
It works perfectly, and I can list all the processes.

HANDLE getProcessHandle(const wchar_t *procName){
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 procEnt;
procEnt.dwSize = sizeof(PROCESSENTRY32);
Process32First(snap, &procEnt);
printf("--Listando procesos...\n");
do{
    printf("Process name: %S \n", procEnt.szExeFile);
    if (!wcscmp(procName, procEnt.szExeFile)){
        printf("Encontrado %S.\n\n", procName);
        return OpenProcess(PROCESS_ALL_ACCESS, FALSE, procEnt.th32ProcessID);
    }
} while (Process32Next(snap, &procEnt));
printf("No se ha encontrado el proceso.");
CloseHandle(snap);
return NULL;

Second, the getModule function. Its work should be finding and enumerating all the modules in the process passed as a HANDLE.

HMODULE getHModule(HANDLE procHandle, const wchar_t *procName){
HMODULE moduleHandle[1024];
DWORD bytesNeeded;
unsigned int i = 0;
if (EnumProcessModulesEx(procHandle, moduleHandle, sizeof(moduleHandle), &bytesNeeded, LIST_MODULES_ALL)){
    printf("--Modulos del proceso:\n");
    for (i = 0; i < (bytesNeeded / sizeof(HMODULE)); i++){
        TCHAR pathModule[1024];
        GetModuleBaseName(procHandle, moduleHandle[i], pathModule, sizeof(pathModule) / sizeof(TCHAR));
        if (!wcscmp(procName, pathModule)){
            printf("Encontrado modulo %S.", procName);
            return moduleHandle[i];
        }
        printf("Module %d: %S \n", i + 1, pathModule);
    }
    printf("No se ha encontrado el modulo.");
    return NULL;
}
else {
    printf("Error en EnumProcessModulesEx n: %ls", GetLastError());
}
return NULL;

And the problem comes here. When I try to enumerate all the modules in the process, if the process is a normal process, I mean, a not-memory-protected process, it works perfectly.
The problem is when the process is memory-protected.
At this point, I decided to search, and I discovered the Privilege Tokens. It's said that if I get the SE_DEBUG_NAME token activated, my process could surpass the protection, so, I've done that function:

int privileges(){
HANDLE token;
TOKEN_PRIVILEGES tp;
DWORD siz = sizeof(TOKEN_PRIVILEGES);

if (OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &token) != 0){
    LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
    tp.PrivilegeCount = 1;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    if (AdjustTokenPrivileges(token, 0, &tp, siz, NULL ,NULL) != 0){
        cout << "--Conseguido acceso debug.\n";
        return TRUE;
    }
    else {
        cout << "fail adjust\n";
        return FALSE;
    }
}
else {
    cout << "fail if: " << GetLastError() << endl;
    cin.get();
    return FALSE;
}

And the "main" function:

int _tmain(int argc, _TCHAR* argv[])
{
privileges();
wchar_t *processName = _T("calc.exe");
HANDLE hProc = getProcessHandle(processName);
  if (hProc){
      HMODULE hMod = getHModule(hProc, processName);
      cout << hMod;
  }
cin.get();
return 0;
}

The problem I have right now is, when I execute this function, privileges() , it returns the ERROR_NO_TOKEN code number.
Someone here said me to change the OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &token) for an OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token) , and that causes no problem, neither result, with that fix, I have the same problem as if privileges() is not executed.
Thanks for reading all the text, and, if is there another way to do this, please tell me, I'm trying to learn.

The documentation for EnumProcessModulesEx says:

This function is intended primarily for 64-bit applications. If the function is called by a 32-bit application running under WOW64, the dwFilterFlag option is ignored and the function provides the same results as the EnumProcessModules function.

Going to the documentation for EnumProcessModules , we find:

If this function is called from a 32-bit application running on WOW64, it can only enumerate the modules of a 32-bit process.

So to work on a 64-bit process, your code will have to be 64-bit itself.

The documentation continues:

If the process is a 64-bit process, this function fails and the last error code is ERROR_PARTIAL_COPY (299).

It seems that this may be incorrect, since you were receiving a access violation exception instead.

Write ImpersonateSelf(SecurityImpersonation); like here:

ImpersonateSelf(SecurityImpersonation);
OpenThreadToken
(
    GetCurrentThread(),
    TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 
    FALSE, 
    &token
);

The ImpersonateSelf makes function obtains an access token that impersonates the security context of the calling process. The token is assigned to the calling thread.

To see all the SECURITY_IMPERSONATION_LEVELs click here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM