码迷,mamicode.com
首页 > 编程语言 > 详细

利用API注入线程

时间:2015-05-12 13:41:55      阅读:140      评论:0      收藏:0      [点我收藏+]

标签:

//提升进程访问权限 
bool enableDebugPriv()  
{  
    HANDLE hToken;  
    LUID sedebugnameValue;  
    TOKEN_PRIVILEGES tkp;  

    if (!OpenProcessToken(GetCurrentProcess(),   
        TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {  
        return false;  
    }  
    if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue)) {  
        CloseHandle(hToken);  
        return false;  
    }  
    tkp.PrivilegeCount = 1;  
    tkp.Privileges[0].Luid = sedebugnameValue;  
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;  
    if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL)) {  
        CloseHandle(hToken);  
        return false;  
    }  
    return true;  
}  

struct ToRemoteProccess
{
    char title[256];
    char content[256];
    DWORD MsgBoxAddress;
};

////定义MessageBox类型的函数指针  
typedef void (__stdcall *Msgbox)(HWND hWnd,LPCTSTR title,LPCTSTR content,DWORD uType );
DWORD threadProc(LPVOID lParam)
{
//  //程序崩溃
//     MessageBox(NULL, "title", "content", MB_OK);
/*****************************************************************************************************
线程体修改完毕之后我们运行程序,将线程注入到宿主进程之中。不过此时会产生一个非法访问的错误。原
因就是线程体中的MessageBox(NULL, "title", "content", MB_OK);函数的第二和第三个参数所指向的字符串
是存在于当前进程的地址空间中,宿主进程中的线程访问该字符串"hello"就会出现访问内存非法的错误。
解决的方法就是将该字符串的内容也拷贝到宿主进程的地址空间中,而且连同MessageBox函数在User32.dll
中的地址也拷贝到宿主进程之中。                                                                    
*****************************************************************************************************/

    //正确执行
    ToRemoteProccess *tmpTRP = (ToRemoteProccess *)lParam;
    Msgbox tmpMsgbox;
    tmpMsgbox = (Msgbox)(tmpTRP->MsgBoxAddress);
    tmpMsgbox(0,tmpTRP->content,tmpTRP->title,0);

    //正确执行
//     __asm
//  {
//      mov eax,0x00401480
//      call eax
//  }

    return 0;
}

void CRemoteCallerDlg::OnButton1() 
{
    // TODO: Add your control notification handler code here

    //提升本程序的权限
    enableDebugPriv();

    //获得远程进程句柄
    HWND hWnd=::FindWindow(NULL,_T("BloodTest"));
    //目标进程ID
    DWORD dwProcessId;
    //目标线程ID
    DWORD dwThreadId;
    dwThreadId=::GetWindowThreadProcessId(hWnd,&dwProcessId);
    //目标进程句柄
    HANDLE HandlToRemoteProcess=::OpenProcess(PROCESS_ALL_ACCESS,false,dwProcessId);
    if(HandlToRemoteProcess == NULL)
    {
        AfxMessageBox(_T("OpenProcess失败"));
        return;
    }

    //申请线程函数内存
    const DWORD dwThreadSize = 4096;
    void* threadProcAddr=::VirtualAllocEx(HandlToRemoteProcess,0,dwThreadSize,MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if(threadProcAddr == NULL)
    {
        AfxMessageBox(_T("VirtualAllocEx失败"));
        return;
    }

    //将线程代码写入到远程进程
    DWORD NumberOfBytesWrittenOfProc;
    BOOL retWriteProcessMemory=::WriteProcessMemory(HandlToRemoteProcess,threadProcAddr,&threadProc, dwThreadSize, &NumberOfBytesWrittenOfProc);
    if(!retWriteProcessMemory)
    {
        AfxMessageBox(_T("WriteProcessMemory失败"));
        return;
    }

    //构造线程参数
    DWORD NumberOfBytesWrittenOfParam;
    ToRemoteProccess trp;
    ZeroMemory(&trp,sizeof(ToRemoteProccess));
    HMODULE hUser32 = LoadLibrary("User32.dll");
    trp.MsgBoxAddress = (DWORD)GetProcAddress(hUser32,"MessageBoxA");
    _sntprintf(trp.title,sizeof("title"),"%s","title");
    _sntprintf(trp.content,sizeof("content"),"%s","content");

    //申请参数空间
    ToRemoteProccess *pRemoteParamAddr = (ToRemoteProccess *)::VirtualAllocEx(HandlToRemoteProcess,0,sizeof(ToRemoteProccess),MEM_COMMIT,PAGE_READWRITE);
    if(pRemoteParamAddr == NULL)
    {
        AfxMessageBox(_T("VirtualAllocEx失败"));
        return;
    }
    //参数写进内存
    retWriteProcessMemory =::WriteProcessMemory(HandlToRemoteProcess,pRemoteParamAddr,&trp, sizeof(ToRemoteProccess), &NumberOfBytesWrittenOfParam);
    if(!retWriteProcessMemory)
    {
        AfxMessageBox(_T("WriteProcessMemory失败"));
        return;
    }

    //创建远程线程
    DWORD RemoteThreadId;
    HANDLE retRemoteThread=::CreateRemoteThread(HandlToRemoteProcess,NULL,0,(LPTHREAD_START_ROUTINE)threadProcAddr,(LPVOID)pRemoteParamAddr,0 ,&RemoteThreadId);
    if (retRemoteThread == NULL)
    {
        AfxMessageBox(_T("CreateRemoteThread失败"));
        return;
    }

    //清理
    VirtualFreeEx(HandlToRemoteProcess,threadProcAddr,dwThreadSize,MEM_RELEASE);
    VirtualFreeEx(HandlToRemoteProcess,pRemoteParamAddr,sizeof(ToRemoteProccess),MEM_RELEASE);

    FreeLibrary(hUser32);
    CloseHandle(HandlToRemoteProcess);

//////////////////////////////////////////////////////////////////////////
//     LPVOID VirtualAllocEx( 
//     HANDLE hProcess, 
//     LPVOID lpAddress, 
//     SIZE_T dwSize, 
//     DWORD flAllocationType, 
//     DWORD flProtect 
//     ); 
// 
//     hProcess:
//     申请内存所在的进程句柄。
//     lpAddress: 
//     保留页面的内存地址;一般用NULL自动分配 。
//     dwSize:
//     欲分配的内存大小,字节单位;注意实际分 配的内存大小是页内存大小的整数倍 
// 
//     flAllocationType 可取下列值:
//     MEM_COMMIT:为特定的页面区域分配内存中或磁盘的页面文件中的物理存储
//     MEM_PHYSICAL :分配物理内存(仅用于地址窗口扩展内存)
//     MEM_RESERVE:保留进程的虚拟地址空间,而不分配任何物理存储。保留页面可通过继续调用VirtualAlloc()而被占用
//     MEM_RESET :指明在内存中由参数lpAddress和dwSize指定的数据无效 
//     MEM_TOP_DOWN:在尽可能高的地址上分配内存(Windows 98忽略此标志)
//     MEM_WRITE_WATCH:必须与MEM_RESERVE一起指定,使系统跟踪那些被写入分配区域的页面(仅针对Windows 98)
// 
//     flProtect可取下列值:
//     PAGE_READONLY: 该区域为只读。如果应用程序试图访问区域中的页的时候,将会被拒绝访
//     PAGE_READWRITE 区域可被应用程序读写
//     PAGE_EXECUTE: 区域包含可被系统执行的代码。试图读写该区域的操作将被拒绝。
//     PAGE_EXECUTE_READ :区域包含可执行代码,应用程序可以读该区域。
//     PAGE_EXECUTE_READWRITE: 区域包含可执行代码,应用程序可以读写该区域。
//     PAGE_GUARD: 区域第一次被访问时进入一个STATUS_GUARD_PAGE异常,这个标志要和其他保护标志合并使用,表明区域被第一次访问的权限
//     PAGE_NOACCESS: 任何访问该区域的操作将被拒绝
//     PAGE_NOCACHE: RAM中的页映射到该区域时将不会被微处理器缓存(cached)
// 
//     注:PAGE_GUARD和PAGE_NOCHACHE标志可以和其他标志合并使用以进一步指定页的特征。PAGE_GUARD标志指定了一个防护页(guard page),即当一个页被提交时会因第一
//     次被访问而产生一个one-shot异常,接着取得指定的访问权限。PAGE_NOCACHE防止当它映射到虚拟页的时候被微处理器缓存。这个标志方便设备驱动使用直接内存访问方
//     式(DMA)来共享内存块。
// 
//     返回值:
//     执行成功就返回分配内存的首地址,不成功就是NULL。
//  
//     
//  BOOL WriteProcessMemory(
//    HANDLE hProcess,
//    LPVOID lpBaseAddress,
//    LPVOID lpBuffer,
//    DWORD nSize,
//    LPDWORD lpNumberOfBytesWritten
//  );
//    
//  参数:
//      hProcess:由OpenProcess返回的进程句柄。如参数传数据为 INVALID_HANDLE_VALUE 【即-1】目标进程为自身进程
//      lpBaseAddress:要写的内存首地址,再写入之前,此函数将先检查目标地址是否可用,并能容纳待写入的数据。
//      lpBuffer:指向要写的数据的指针。
//      nSize:要写入的字节数。
//      lpNumberOfBytesWritten:成功写入的数据的大小
//      
//  返回值:
//        非零值代表成功.
// 
//  HANDLE CreateRemoteThread(
//    HANDLE hProcess,
//    LPSECURITY_ATTRIBUTES lpThreadAttributes,
//    SIZE_T dwStackSize,
//    LPTHREAD_START_ROUTINE lpStartAddress,
//    LPVOID lpParameter,
//    DWORD dwCreationFlags,
//    LPDWORD lpThreadId
//  );
//  参数说明:
//    hProcess:目标进程的句柄
//    lpThreadAttributes:指向线程的安全描述结构体的指针,一般设置为NULL,表示使用默认的安全级别
//    dwStackSize:线程堆栈大小,一般设置为0,表示使用默认的大小,一般为1M
//    lpStartAddress:线程函数的地址
//    lpParameter:线程参数
//    dwCreationFlags:线程的创建方式
//    lpThreadId:输出参数,记录创建的远程线程的ID
//////////////////////////////////////////////////////////////////////////

}

利用API注入线程

标签:

原文地址:http://blog.csdn.net/liujiayu2/article/details/45667773

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!