【问题标题】:C Shellcode 32bit vs 64bit [closed]C Shellcode 32bit vs 64bit [关闭]
【发布时间】:2020-10-28 22:05:30
【问题描述】:

我编写了一个程序,将函数写入文件,然后加载所述文件并执行该函数。当我为 32 位编译时,这段代码没有问题,但是当我将编译器设置为 64 位时,程序崩溃了。

    #include <stdio.h>
    #include <windows.h>
    #include <Filez.h>

    void shellc(FARPROC p,char* x)
    {
    (int (WINAPI *)(HWND,LPCSTR,LPCSTR,UINT))p(NULL,x,x,MB_OK);
    }
    void stub()
    {
    
    }
    
    int main(int argc, char **argv)
    {
    int size = stub - shellc;
    CryptMemoryToFile(shellc,size,"somepassword","shellcodefile");
    int sz;
    char * x = DeCryptFileToMemory("shellcodefile","somepassword",&sz);
    void (*shellcode)(FARPROC,char*) = x;
    FARPROC p = GetProcAddress(LoadLibraryA("user32.dll"),"MessageBoxA");
    shellcode(p,"test");
    
    getchar();
    }

Filez.h 中定义的 2 个 (De)Cryption 函数

    char * DeCryptFileToMemory(char * File,char * Pw,int * Size)
    {
    int PWL = strlen(Pw);
    char * Data = LoadFile(File,Size);
    if (Data == NULL) return 0;

    int y = 0;
    for (int x = 0; x <= *Size;x++)
    {
    Data[x] = Data[x] - Pw[y];
    y++;
    if (y > PWL) y = 0;
    }

    return Data;
    }

    int CryptMemoryToFile(char * Memory,int Size,char * Pw,char *                 File)
    {
    int PWL = strlen(Pw);
    char * Memory2 = malloc(Size);
    memcpy(Memory2,Memory,Size);
        
    if (Memory2 == NULL) return 0;
    
    int y = 0;
    for (int x = 0; x <= Size;x++)
    {
    Memory2[x] = Memory2[x] + Pw[y];
    y++;
    if (y > PWL) y = 0;
    }
    
    FILE * f = fopen(File,"wb");
    if (f == NULL) return 0;
    int w = fwrite(Memory2,1,Size,f); 
    if (w != Size) return 0;
    fclose(f);
    free(Memory2);
    return 1;
    
    }

【问题讨论】:

  • 当您将其放入调试器并逐步执行时,您是否发现任何异常?会发生什么样的崩溃?

标签: c windows shellcode


【解决方案1】:

您不能只将 x86 shellcode 移动到 x64 并期望它自然而然地工作。 x86 程序集和 x64 程序集之间存在很大差异。具体与如何在堆栈/寄存器上传递参数以及使用哪些寄存器有关。

您的 shellcode 在 x64 中无法运行的原因可能与堆栈未对齐或寄存器使用不正确有关。您可能正在保存 x86 部分,然后尝试在 x64 中使用相同的 shellcode。您可能还试图执行不可执行的内存区域。可能有很多原因。

我用 x64 给你写了一个简单的 shellcode。第一个参数是地址,而第二个参数是要显示的消息。请注意,这在 x86 中不起作用。

unsigned char shellcode[] = {
0x56, 0x48, 0x8B, 0xF1, 0x48, 0xC7, 0xC1, 0x00, 0x00, 0x00, 0x00, 
0x4C, 0x8B, 0xC2, 0x49, 0xC7, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x48, 
0x83, 0xEC, 0x20, 0xFF, 0xD6, 0x48, 0x83, 0xC4, 0x20, 0x5E, 0xC3
};
void CallMB(FARPROC MessageBoxAddress,char* Message){
//here make a function pointer to shellcode which takes two argumenst
//the address and the buffer.
//call the pointer
}

我也不知道您是如何将 shell 代码保存到文件中的。如果它是二进制文件或文本文件。但是只要内存区域是可执行的,也可以直接在您的代码中调用该 shellcode。

【讨论】:

  • 我没有尝试使用 32 位 shellcode,我将整个程序重新编译为 64 位,因此写入文件的函数也应该是 64 位
  • 更新:我现在开始工作了,这次我使用了带有 PAGE_EXECUTE_READWRITE 的 VirtualAlloc,然后将 shellcode 从文件复制到新分配的内存中,我唯一想知道的是为什么我只需要这样做编译 64 位可执行文件而不是 32 位和 64 位时
  • 您需要在没有执行权限的内存区域上设置页面保护。为什么在 x86 中不需要这样做超出了我的理解,并且似乎是未定义的行为,或者你只是幸运..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-06
  • 2010-11-12
  • 1970-01-01
  • 2011-09-09
  • 1970-01-01
  • 1970-01-01
  • 2012-01-16
相关资源
最近更新 更多