从进程内存中读取字符串

时间:2014-06-24 20:51:50

标签: c++ string memory

const char* GetName()
{
    std::string s = *(std::string*)(this + 0x28);
    return s.c_str();
}

更新

struct Entity
{
    static Entity* GetCurrentPlayer()
    {
        return  (Entity*)(*(DWORD*)((DWORD)GetModuleHandleA("League of Legends.exe") + (DWORD)ADR_LocalPlayer));
    }
}

UPDATE2:

This is how it looks in Cheat Engine

实际上,我需要做的就像Cheat Engine一样:读取位于某个指针的字符串(this)+ Offset 0x28作为const char *返回,因为我需要此数据类型。

我也尝试用const char *直接访问地址,这给了我神秘的符号。顶部的示例正在崩溃游戏。

我想我需要另一种数据类型或其他方式来访问数据?!

注意:这是一个注入的DLL,我通过地址访问数据

2 个答案:

答案 0 :(得分:1)

我认为这就是你需要的,将目标地址设置为Read,Write和Execute(如果你想改变代码)。

VirtualProtect的((LPVOID)的targetAddress,5,PAGE_EXECUTE_READWRITE,&安培; oldp);

这是一个完整的场景:

  1. 使用共享内存部分编写DLL。 DLL应链接到您的主应用程序以启用接收通知或数据(字符串),并在您需要控制远程进程时启用从主应用程序发送命令。

  2. 您的主应用程序应该创建远程线程,该线程中的代码将是将DLL加载到远程进程中,然后DLL应该从那里接管。

  3. 使用您选择的进程间通信机制,开始在远程进程和主应用程序之间发送/接收数据。

  4. 这是一个DLL注入功能(在你的主应用程序中),用于将你的DLL注入远程进程:

    int Inject(char *fname,char *dllname,int NewProcess,DWORD PID) // 1=new process, 2= PID, 3=current process
    {
        STARTUPINFOA si;
        PROCESS_INFORMATION pi;
        BOOL rv;
        void *pr;
        HANDLE hh;
        SIZE_T bwrit;
        DWORD par,tid;HANDLE th;
        FARPROC LoadLibProc = GetProcAddress(GetModuleHandleA("KERNEL32.dll"), "LoadLibraryA");
        FARPROC ExitThreadProc = GetProcAddress(GetModuleHandleA("KERNEL32.dll"), "ExitThread");
        char InjectedCode[500] = 
    
            {// 0xcc,
                0x60,        // pushad
                0xB8, 00, 00, 00, 00,   // mov EAX,  0h | Pointer to LoadLibraryA() (DWORD)
                0xBB, 00, 00, 00, 00,   // mov EBX,  0h | DLLName to inject (DWORD)
                0x53,                   // push EBX
                0xFF, 0xD0,             // call EAX
                0x5b,                   // pop EBX
                0xB8, 00, 00, 00, 00,   // EAX 2 mov EAX,  0h | Pointer to ExitThreadProc() (DWORD)
                0x6a,00,         // Push 00
                0xFF, 0xD0,             // call EAX
    
                //0xcc                  // INT 3h
        0x61,                 // popad
        //0xcc
            //  0xc3 // ret
            };
    
                int nob=30;
    
                char *DLLName;
                DWORD *EAX, *EBX, *EAX2;
    
                DLLName = (char*)((DWORD)InjectedCode + nob);
                strcpy( DLLName, dllname );
                EAX = (DWORD*)( InjectedCode +  2);
                EBX = (DWORD*) ( InjectedCode +  7);
    
                EAX2 = (DWORD*)( InjectedCode +  16);
    
        *EAX=(DWORD)LoadLibProc;
        *EAX2=(DWORD)ExitThreadProc;
        *EBX=nob;
    
        ZeroMemory((VOID*)&si, sizeof(si));
        si.dwFlags=STARTF_USESHOWWINDOW;//1
        si.wShowWindow=SW_HIDE;//0
    
        if (NewProcess==1) {
            rv=CreateProcessA(fname,0,0,0,FALSE,CREATE_SUSPENDED,0,0,&si,&pi);
            if (rv==FALSE) {return -1;}
            hh=pi.hProcess;
        }
    
        TCHAR bb[200];
        if (NewProcess==2) {////PROCESS_ALL_ACCESS
            hh=OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_WRITE|PROCESS_VM_OPERATION  ,0,PID);
            if (hh==NULL) return -6;
        }
    
        if (NewProcess==3) {
            hh=GetCurrentProcess();
        }
    
        //if (hh==INVALID_HANDLE_VALUE) {printf("\nError Opening Process...");return;}
        pr=VirtualAllocEx(hh,0,500,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
        if (pr==NULL) return -7;
        Sleep(100);
        //printf("\nAddress Allocated=%x",pr);
        *EBX+=(DWORD)pr;
    
        rv=WriteProcessMemory(hh,pr,InjectedCode,500,&bwrit);
        if (rv==0) return -8;
    
        th=CreateRemoteThread(hh,NULL,0,(LPTHREAD_START_ROUTINE)pr,&par,0,&tid);
    
        if (th==NULL) return -9;
            return 0;
    }
    

    现在,对于DLL,在DLL CPP中,添加共享内存部分以保存用于进程间通信的数据:

        #pragma data_seg("shared")
    
        char whateverdatatoshare[16384]={0}; 
    
    // you can also define events or variables to use to signal the remote process or the main app of any incoming data
    
    
    #pragma data_seg()
    #pragma comment(linker, "/section:shared,rws") // This instructs the linker to make this section readable,writable and shared
    

    在您的APIENTRY dllmain函数中,创建一个线程来执行您想要的任何操作,例如每秒读取您的字符串或数据以将其发送回主应用程序。

    BOOL APIENTRY DllMain1( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
    {
    DWORD par,tid;
    HANDLE thandle;
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    
        thandle= CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)&MsgThread,&par,0,&tid);
    
        break;
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
    
        break;
    }
    return TRUE;
    

    }

    你的线程代码应该执行嗅探你想要的字符串的实际工作。

    非常重要:要确保您可以在内存中读/写,请使用:

    首先将页面设置为PAGE_EXECUTE_READWRITE

    **VirtualProtect((LPVOID)targetaddress,5,PAGE_EXECUTE_READWRITE,&oldp);**
    

    第二:IsBadWritePtr或IsBadReadPtr,以确保您可以写或读。

答案 1 :(得分:0)

史蒂夫已经提到过,由于受到操作系统的保护,你无法访问其他应用程序的内存。您可以通过运行两个小程序来检查,第一个创建一个变量,将其指针存储在一个文件中并在此之后继续运行(通过等待用户输入或其他)。第二个程序从文件中读取指针,然后尝试使用其内容。不会工作。

此外,请查看GetModuleHandleA的文档:http://msdn.microsoft.com/en-us/library/windows/desktop/ms683199%28v=vs.85%29.aspx

它说:

"检索指定模块的模块句柄。该模块必须已由调用进程加载。"

"将名称与当前映射到调用进程的地址空间的模块的名称进行比较(大小写独立)。"

由于你想获得一个由另一个进程加载的模块,这也无法正常工作。