【问题标题】:Re-write segment of a compiled C program重写已编译 C 程序的段
【发布时间】:2019-02-05 19:57:19
【问题描述】:

我有一个这样构造的 C 程序:

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

#pragma section(".code",execute, read, write)
#pragma comment(linker,"/SECTION:.code,ERW")
#pragma code_seg(".code")

//Code to decrypt

#pragma section(".stub", execute, read, write)
#pragma code_seg(".stub")

void decryptor(){
    //Retrieve virtual address of the pointer to the .code section
    //Retrieve the virtual size of the pointer to the .code section
    for(int i = 0; i<size; i++){
         //HERE THE PROGRAM STOPS
         ptrCode[0] = //Reverse function of the encryptor
    }
}

int main(){
    decryptor();
    mainFunctionDecrypted();
    return 0;
}

基本上我有一个加密器,它在编译后首先加密这个程序的 exe 中的 .code 段。 然后,当我执行修改后的 exe 时,我希望能够先对其进行解密,然后再执行解密的部分。但是,我似乎无法写入加载到内存中的 .code 段(我认为是因为它是专用于要执行的代码的部分内存)。

有没有办法写入可执行内存?

你有什么变通的方法吗?

【问题讨论】:

    标签: c visual-studio encryption memory-management segment


    【解决方案1】:

    Windows 和其他操作系统会竭尽全力阻止您执行此操作(修改正在运行的应用程序的代码部分)。

    那么,你的直接选择是

    1) 将代码解密到为此目的动态分配的某个其他内存区域(代码必须要么仅使用与位置无关的指令,要么包含针对具有特定位置数据的指令的自定义修复)。

    2) 使用单独的程序在执行前解密磁盘上的程序。

    【讨论】:

    • 假设我使用与位置无关的指令(为了简洁起见),一旦我动态分配了所需的内存并解密了那里的段,我应该怎么做才能调用mainFunctionDecrypted()?更清楚地说,我该怎么做才能访问这些功能?无论如何感谢您的快速回复
    • 要调用代码,请使用函数指针。当然,具体的语法因编程语言而异。
    【解决方案2】:

    以这种方式混淆程序本质上是徒劳的。无论你的“解密器”做什么,一个决心对你的程序进行逆向工程的人也可以做。把你的精力花在让你的程序足够受欢迎,让人们想要为它付钱,并且足够仁慈,你不必隐瞒它在做什么。

    【讨论】:

      【解决方案3】:

      我需要通过以下方式修改代码。此外,Visual Studio 中还有一些重要的编译器选项需要设置,例如禁用数据执行保护。

      使用的编译器选项: /permissive- /GS /TC /GL /analyze- /W3 /Gy /Zc:wchar_t /Gm- /O2 /sdl /Zc:inline /fp:precise /Zp1 /D "_MBCS" /errorReport:prompt /WX- / Zc:forScope /GR- /Gd /Oy- /Oi /MD /FC /nologo /diagnostics:classic

      使用的链接器选项: /MANIFEST /LTCG: 增量 /NXCOMPAT:NO /DYNAMICBASE:NO “kernel32.lib” “user32.lib” “gdi32.lib” “winspool.lib” “comdlg32.lib” “advapi32.lib” “shell32.lib” “ ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /FIXED /MACHINE:X86 /OPT:REF /SAFESEH /INCREMENTAL:NO /SUBSYSTEM:CONSOLE /MANIFESTUAC:"level= 'asInvoker' uiAccess='false'" /MAP /OPT:ICF /ERRORREPORT:PROMPT /NOLOGO /TLBID:1

      #pragma section(".code", execute, read)
      #pragma section(".codedata", read, write)
      #pragma comment(linker,"/SECTION:.code,ERW")
      #pragma comment(linker,"/SECTION:.codedata,ERW")
      #pragma comment(linker, "/MERGE:.codedata=.code")
      
      //All the following will go in code
      #pragma code_seg(".code")
      #pragma data_seg(".codedata")
      #pragma const_seg(".codedata")
      
      //CODE TO DECRYPT
      
      // .stub SECTION
      #pragma section(".stub", execute, read)
      #pragma section(".stubdata", read, write)
      #pragma comment(linker,"/SECTION:.stub,ERW")
      #pragma comment(linker,"/SECTION:.stubdata,ERW")
      #pragma comment(linker, "/MERGE:.stubdata=.stub")
      
      //All the following will go in .stub segment
      #pragma code_seg(".stub")
      #pragma data_seg(".stubdata")
      #pragma const_seg(".stubdata")
      
      /*This function needs to be changed to whatever correspond to the decryption function of the encryotion function used by the encryptor*/
      void decryptCodeSection(){
      
           //Retrieve virtual address of the pointer to the .code section
           //Retrieve the virtual size of the pointer to the .code section
           for(int i = 0; i<size; i++){
                //HERE THE PROGRAM STOPS
                ptrCode[0] = //Reverse function of the encryptor
            }
      
      void main(int argc, char* argv[]){
          decryptor();
          mainFunctionDecrypted();
      }
      

      这样做我能够首先解密段然后执行函数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-08
        • 2011-02-14
        • 2016-02-01
        • 2011-01-03
        相关资源
        最近更新 更多