jjzjj

c++ - 通过从 C/C++ 调用 Windows API 函数生成独立的汇编子例程

coder 2024-06-08 原文

我做了一些 shellcode 执行的实验,我在其中编写了自己的 shellcode,将其写入我希望它执行的目标程序的内存中,然后使用新线程或线程劫持来执行它。

这很好用,但是手动编写 shellcode 相当耗时,因此我正在寻找一种能够用 C 或 C++ 编写函数的方法,该函数在编译后将完全独立。这意味着任何编译后的函数都应该可以独立执行。这样我就可以直接将它写入我的目标程序中,例如使用 WriteProcessMemory 准备执行。因此,推送 shellcode 将使用如下代码完成:

#include <Windows.h>
#include <iostream>

using namespace std;

BOOL MakeABeep() {
    return Beep(0x500, 0x500);
}
DWORD MakeABeepEnd() { return 0; }

int main() {
    DWORD pid = 0;
    cout << "PID: ";
    cin >> dec >> pid;
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    if (!hProcess) { cout << "OpenProcess failed GLE = " << dec << GetLastError() << endl; return EXIT_FAILURE; }

    void* buf = VirtualAllocEx(hProcess, NULL, 4096, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (!buf) { cout << "VirtualAllocEx failed GLE = " << dec << GetLastError() << endl; return EXIT_FAILURE; }

    SIZE_T size = (DWORD64)MakeABeep - (DWORD64)MakeABeepEnd;
    BOOL wpmStatus = WriteProcessMemory(hProcess, buf, MakeABeep, size, NULL);
    if (!wpmStatus) { cout << "WriteProcessMemory failed GLE = " << dec << GetLastError() << endl; return EXIT_FAILURE; }

    HANDLE hThread = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)buf, NULL, NULL, NULL);
    if (!hThread) { cout << "CreateRemoteThread failed GLE = " << dec << GetLastError() << endl; return EXIT_FAILURE; }
    WaitForSingleObject(hThread, INFINITE);

    VirtualFreeEx(hProcess, buf, 0, MEM_RELEASE);
    return EXIT_SUCCESS;
}

如果用MSVC编译器的默认选项编译,只会复制一堆jmp指令,好像是个跳转表。为了避免这个问题,我在编译器选项中禁用了增量链接,现在函数 MakeABeep 中的所有代码都被正确复制,对导入函数的调用除外。

在我的 shellcode 中,我按照调用约定传递参数,然后将我要调用的函数的地址放入寄存器 rax 中,最后我用 调用函数调用 rax

是否可以让编译器生成类似的东西? 关键是生成的二进制文件必须具有可以独立执行的自包含子例程。

例如,这是为函数 MakeABeep 生成的汇编代码: 为了能够直接运行它,而不是这个 mov rax, QWORD PTR [rip+0x?] 编译器应该将 Beep 函数的完整地址移动到 rax 中。

请忽略与目标程序中可能未加载或加载到不同地址的模块有关的问题,我只是打算调用 kernel32 和 ntdll 中的函数,这些函数肯定已加载并且在不同进程中位于同一地址。

感谢您的帮助。

最佳答案

编译器不知道 Beep 函数的完整地址。 Beep 函数位于 kernel32.dll 中,此 .DLL 标记为 ASLR兼容,理论上可以在每次运行程序时更改其地址。没有编译器功能可以让您在 .DLL 中生成函数的真实地址,因为这样的功能非常无用。

我能想到的一种选择是使用在运行时用正确的函数地址替换的魔术 cookie:

SIZE_T beepaddr = 0xff77ffffffff7001ull; // Magic value
((BOOL(WINAPI*)(DWORD,DWORD))beepaddr)(0x500, 0x500); // Call Beep()

编译为

00011   b9 00 05 00 00   mov     ecx, 1280      ; 00000500H
00016   48 b8 01 70 ff ff ff ff 77 ff    mov     rax, -38280596832686079    ; ff77ffffffff7001H
00020   8b d1        mov     edx, ecx
00022   ff d0        call    rax

然后您必须围绕 WriteProcessMemory 编写一个包装器,它知道如何查找这些魔法值并将其替换为正确的地址。

一些 shell 代码将有自己的 GetModuleHandleGetProcAddress 的迷你实现,它在 PEB 模块列表中查找模块,然后搜索导出目录。他们经常对名称使用迷你哈希函数,因此他们不必处理字符串。

如果您要注入(inject)大量代码,您可能会厌倦这些 hack,并像其他人一样在远程进程中加载​​一个 .DLL。

关于c++ - 通过从 C/C++ 调用 Windows API 函数生成独立的汇编子例程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49879368/

有关c++ - 通过从 C/C++ 调用 Windows API 函数生成独立的汇编子例程的更多相关文章

  1. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

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

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

  3. ruby - 在 jRuby 中使用 'fork' 生成进程的替代方案? - 2

    在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',

  4. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

  5. ruby-on-rails - 独立 ruby​​ 脚本的配置文件 - 2

    我有一个在Linux服务器上运行的ruby​​脚本。它不使用rails或任何东西。它基本上是一个命令行ruby​​脚本,可以像这样传递参数:./ruby_script.rbarg1arg2如何将参数抽象到配置文件(例如yaml文件或其他文件)中?您能否举例说明如何做到这一点?提前谢谢你。 最佳答案 首先,您可以运行一个写入YAML配置文件的独立脚本:require"yaml"File.write("path_to_yaml_file",[arg1,arg2].to_yaml)然后,在您的应用中阅读它:require"yaml"arg

  6. 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

  7. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  8. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  9. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  10. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

随机推荐