仅注入函数并通过CreateRemoteThread运行它? C ++

时间:2015-03-01 15:21:30

标签: windows winapi assembly x86 reverse-engineering

我试图注入此功能:

void  doubleValue(int pointer){
    *((int*)pointer) *= 2;
}

通过VirtualAllocEx&进入流程WriteProcessMemory

int size = 1024 * 1024 * 4;
HANDLE h = GetCurrentProcess();

void * func = &doubleValue;

int arg = (int)&HP;

DWORD adr = (DWORD)VirtualAllocEx(h, 0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(h, (LPVOID)adr, func, size, 0);

unsigned long i = 0;
VirtualProtectEx(h, (LPVOID)(adr - size), size * 2, PAGE_EXECUTE_READWRITE, &i);
HANDLE thread = CreateRemoteThread(h, NULL, 0, (LPTHREAD_START_ROUTINE)(adr), &arg, 0, NULL);

注意: 出于测试目的,我将函数注入到同一个进程(GetCurrentProcess())。

注入时,复制的行是jmp xxxxxxx而不是实际函数;

00660000 - push ebp
00660001 - mov ebp,esp
00660003 - sub esp,000000C0
00660009 - push ebx
0066000A - push esi
0066000B - push edi
0066000C - lea edi,[ebp-000000C0]
00660012 - mov ecx,00000030
00660017 - mov eax,CCCCCCCC
0066001C - repe stosd 
0066001E - mov eax,[ebp+08]
00660021 - mov ecx,[eax]
00660023 - shl ecx,1
00660025 - mov edx,[ebp+08]
00660028 - mov [edx],ecx
0066002A - pop edi
0066002B - pop esi
0066002C - pop ebx
0066002D - mov esp,ebp
0066002F - pop ebp

所以我得到了函数的转储

  

\ X55 \ x8B \ XEC \ X81 \ XEC \ XC0 \ X00 \ X00 \ X00 \ X53 \ X56 \ X57 \ x8D \ XBD \ X40 \ XFF \ XFF \ XFF \ xB9 \ X30 \ X00 \ X00 \ X00 \ XB8 \ XCC \ XCC \ XCC \ XCC \ XF3 \ XAB \ x8B \ X45 \ X08 \ x8B \ X08 \ XD1 \ XE1 \ x8B \ X55 \ X08 \ X89 \ X0A \ X5F \ x5E \ x5B \ x8B \ xE5 \ X5D < / p>

试图写出而不是&amp; func的数据。但仍然没有发生任何事 此外,因为我注入了我自己的进程,跳转地址非常好,而且应该也有效。 [仅测试,我不是试图将代码注入我自己的过程]

来自cheatengine + visualstudio的图片。

ADR = 00443F5B

http://puu.sh/ghRtv/6b87c44154.png

jmp地址:

http://puu.sh/ghRum/a612d67e11.png

无论我改变了多少代码,我都要Access violation executing location 0xXXXXXXXX或字面没有任何事情发生

编辑:我知道我可以写procprocm - &gt;惠普,但这不是重点。

1 个答案:

答案 0 :(得分:5)

嗯,我看不出你的代码到底出了什么问题。

您获得JMP而不是函数代码的事实可能是由于增量链接。

您不需要调用VirtualProtect,因为您已经拥有正确的页面保护标志。

获取函数的一种可能方法是将其设置为可执行文件的另一部分并在运行时获取它。

这是一个简单的例子,错误检查是最小的:

// Test.cpp : Defines the entry point for the console application.
//


#include <stdio.h>
#include <Windows.h>

#define SECTION_NAME ".my_func"

// put the function in its dedicated section
#pragma code_seg (push)
#pragma code_seg(SECTION_NAME)
static int foo = 0;
void  doubleValue(int* pointer){
    *pointer *= 2;
}
#pragma code_seg (pop)


typedef struct _tag_SECTION_INFORMATION {
    // virtual address of the section
    void* section_address;
    // raw size of the section
    DWORD section_size;
} SECTION_INFORMATION;

// given the name of a section, gets information from it.
BOOL GetSectionInformation(char* sec_name, SECTION_INFORMATION* sec_info){
    char current_sec_name[IMAGE_SIZEOF_SHORT_NAME];
    BOOL bresult = FALSE;

    HMODULE hMyself = GetModuleHandle(NULL);
    IMAGE_DOS_HEADER* pidh = (IMAGE_DOS_HEADER*)hMyself;
    IMAGE_NT_HEADERS* pinh = (IMAGE_NT_HEADERS*)((ULONG_PTR)(hMyself)+pidh->e_lfanew);
    WORD numsec = pinh->FileHeader.NumberOfSections;
    IMAGE_SECTION_HEADER* pish = IMAGE_FIRST_SECTION(pinh);
    for (WORD i = 0; i < numsec; ++i){
        memcpy_s(current_sec_name, IMAGE_SIZEOF_SHORT_NAME, &pish->Name, IMAGE_SIZEOF_SHORT_NAME);
        if (memcmp(SECTION_NAME, current_sec_name, IMAGE_SIZEOF_SHORT_NAME) == 0)
        {
            sec_info->section_address = (void*)((ULONG_PTR)hMyself + pish->VirtualAddress);
            sec_info->section_size = pish->SizeOfRawData;
            bresult = TRUE;
            break;
        }

        pish++;
    }

    return bresult;
}

int main(int argc, char *argv[])
{
    SECTION_INFORMATION sec_info;

    // force compiler to not optimize away the function.
    printf("%08lX\n", &doubleValue);

    // get VA and size of section where 'doubleValue' resides.
    if (!GetSectionInformation(SECTION_NAME, &sec_info)) {
        printf("[-] error GetSectionInformation()\n");
        return -1;
    }

    // open this process
    HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,
        FALSE,
        GetCurrentProcessId());
    if (!hProcess){
        printf("[-] Error: couldn't open process...\n");
        return -1;
    }

    // allocate page, size is the size of the section where 'doubleValue' is.
    void* page = VirtualAllocEx(hProcess, NULL, sec_info.section_size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (!page){
        printf("[-] Error: couldn't allocate remote page.\n");
        return -1;
    }

    DWORD nobw = 0;
    if(!WriteProcessMemory(hProcess, page, sec_info.section_address, sec_info.section_size, &nobw) && nobw < sec_info.section_size){
        printf("[-] Error: couldn't write to page.\n");
        return -1;
    }    

    int i = 42;
    printf("parameter: %i\n", i);

    // Note: you should obviously *not* pass an address from this address space to another process address space.
    // It is fine here to pass the address of 'i' as we are still in the same address space.
    if (!CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)page, &i, 0, NULL)){
        printf("[-] CreateRemoteThread() failed.\n");
        return -1;
    }

    Sleep(1000);

    // should print '84'.
    printf("result: %i\n", i);

    return 0;
}

编辑:相同的代码,但在远程进程中,在calc.exe中注入函数,调用doubleValue()函数并从calc.exe读取结果:

#include <stdio.h>
#include <Windows.h>

#define SECTION_NAME ".my_func"

// put the function in its dedicated section
#pragma code_seg (push)
#pragma code_seg(SECTION_NAME)
static int foo = 0;
void  doubleValue(int* pointer){
    *pointer *= 2;
}
#pragma code_seg (pop)


typedef struct _tag_SECTION_INFORMATION {
    // virtual address of the section
    void* section_address;
    // raw size of the section
    DWORD section_size;
} SECTION_INFORMATION;

// given the name of a section, gets information from it.
BOOL GetSectionInformation(char* sec_name, SECTION_INFORMATION* sec_info){
    char current_sec_name[IMAGE_SIZEOF_SHORT_NAME];
    BOOL bresult = FALSE;

    HMODULE hMyself = GetModuleHandle(NULL);
    IMAGE_DOS_HEADER* pidh = (IMAGE_DOS_HEADER*)hMyself;
    IMAGE_NT_HEADERS* pinh = (IMAGE_NT_HEADERS*)((ULONG_PTR)(hMyself)+pidh->e_lfanew);
    WORD numsec = pinh->FileHeader.NumberOfSections;
    IMAGE_SECTION_HEADER* pish = IMAGE_FIRST_SECTION(pinh);
    for (WORD i = 0; i < numsec; ++i){
        memcpy_s(current_sec_name, IMAGE_SIZEOF_SHORT_NAME, &pish->Name, IMAGE_SIZEOF_SHORT_NAME);
        if (memcmp(SECTION_NAME, current_sec_name, IMAGE_SIZEOF_SHORT_NAME) == 0)
        {
            sec_info->section_address = (void*)((ULONG_PTR)hMyself + pish->VirtualAddress);
            sec_info->section_size = pish->SizeOfRawData;
            bresult = TRUE;
            break;
        }

        pish++;
    }

    return bresult;
}

int main(int argc, char *argv[])
{
    SECTION_INFORMATION sec_info;

    // force compiler to not optimize away the function.
    printf("%08lX\n", &doubleValue);

    // get VA and size of section where 'doubleValue' resides.
    if (!GetSectionInformation(SECTION_NAME, &sec_info)) {
        printf("[-] error GetSectionInformation()\n");
        return -1;
    }

    PROCESS_INFORMATION pi = { 0 };
    STARTUPINFO si = { 0 };
    si.cb = sizeof(STARTUPINFO);
    if (!CreateProcessW(L"c:\\windows\\system32\\calc.exe", NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)){
        printf("[-] Error: couldn't create process.\n");
        return -1;
    }

    // open this process
    HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,
        FALSE,
        pi.dwProcessId);
    if (!hProcess){
        printf("[-] Error: couldn't open process...\n");
        return -1;
    }

    // allocate page for function code, size is the size of the section where 'doubleValue' is.
    void* page_function = VirtualAllocEx(hProcess, NULL, sec_info.section_size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (!page_function){
        printf("[-] Error: couldn't allocate remote page for function code.\n");
        return -1;
    }

    // write function code to remote process.
    DWORD nobw = 0;
    if (!WriteProcessMemory(hProcess, page_function, sec_info.section_address, sec_info.section_size, &nobw) && nobw < sec_info.section_size){
        printf("[-] Error: couldn't write to code page.\n");
        return -1;
    }

    // page for result
    void* page_result = VirtualAllocEx(hProcess, NULL, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (!page_result){
        printf("[-] Error: couldn't allocate remote page for result.\n");
        return -1;
    }

    int i = 42;
    printf("parameter: %i\n", i);
    // write parameter to remote process.
    nobw = 0;
    if (!WriteProcessMemory(hProcess, page_result, &i, sizeof(i), &nobw) && nobw < sizeof(i)){
        printf("[-] Error: couldn't write to result page.\n");
        return -1;
    }

    // call remote doubleValue() function, passing the address where the argument lies (42)
    if (!CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)page_function, page_result, 0, NULL)){
        printf("[-] CreateRemoteThread() failed.\n");
        return -1;
    }

    Sleep(1000);

    // now read result in remote process, should be: 84.
    DWORD nobr;
    if (!ReadProcessMemory(hProcess, page_result, &i, sizeof(i), &nobr)){
        printf("[-] ReadProcessMemory failed.\n");
        return -1;
    }

    // should print '84'.
    printf("result: %i\n", i);

    return 0;
}