jjzjj

windows - 仅注入(inject)函数并通过 CreateRemoteThread 运行它? C++

coder 2023-11-12 原文

我正在尝试注入(inject)这个函数:

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);

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

注入(inject)时复制的行是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

并尝试写入它而不是 &func 的数据。但仍然没有任何反应。 另外,由于我将跳转地址注入(inject)到我自己的进程中,所以它非常好,而且应该也能正常工作。 [仅测试,我不会尝试将代码注入(inject)我自己的进程]

图片来自cheatengine+visualstudio。

adr=00443F5B

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

跳转地址:

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

无论我如何更改代码,我都会得到 Access violation executing location 0xXXXXXXXX 或字面上的什么都没有发生

编辑:我知道我可以只写 procmem -> HP,但这不是重点。

最佳答案

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

您获得 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;
}

编辑:相同的代码,但在远程进程中,将函数注入(inject) 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;
}

关于windows - 仅注入(inject)函数并通过 CreateRemoteThread 运行它? C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28795242/

有关windows - 仅注入(inject)函数并通过 CreateRemoteThread 运行它? C++的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  3. ruby - 通过 rvm 升级 ruby​​gems 的问题 - 2

    尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub

  4. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

  5. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  6. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  7. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  8. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  9. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  10. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

随机推荐