Переписать сегмент скомпилированной программы на C

У меня есть программа 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;
}

По сути, у меня есть шифратор, который сначала шифрует сегмент .code в exe этой программы после компиляции. Затем, когда я запускаю модифицированный exe, я хочу иметь возможность сначала расшифровать его, а затем выполнить расшифрованную часть. Однако кажется, что я не могу писать в сегмент .code, загруженный в память (я думаю, потому что это часть памяти, предназначенная для выполнения кода).

Есть ли способ записи в исполняемую память?

Есть ли какой-нибудь обходной путь, который вы бы сделали?


person Luca Reccia    schedule 30.08.2018    source источник


Ответы (3)


Windows и другие операционные системы делают все возможное, чтобы помешать вам сделать это (изменить разделы кода работающего приложения).

Тогда ваши непосредственные варианты

1) расшифровать код в какую-либо другую область памяти, динамически выделенную для этой цели (тогда код должен либо использовать только независимые от позиции инструкции, либо содержать пользовательские исправления для инструкций, которые имеют данные, специфичные для позиции).

2) использовать отдельную программу, которая расшифровывает программу на диске перед ее выполнением.

person 500 - Internal Server Error    schedule 30.08.2018
comment
Предполагая, что я использую независимую от позиции инструкцию (для простоты), после того, как я динамически выделил требуемую память и расшифровал сегмент, что я должен сделать, чтобы иметь возможность вызывать mainFunctionDecrypted()? Чтобы быть более ясным, что мне нужно сделать, чтобы получить доступ к этой функции? В любом случае спасибо за быстрый ответ - person Luca Reccia; 30.08.2018
comment
Чтобы вызвать код, используйте указатель функции. Точный синтаксис для этого, конечно, зависит от языка программирования. - person 500 - Internal Server Error; 31.08.2018

Обфускация программы таким образом по своей сути бесполезна. Что бы ни делал ваш «дешифратор», человек, решивший перепроектировать вашу программу, тоже может это сделать. Вместо этого потратьте свои усилия на то, чтобы сделать вашу программу достаточно привлекательной, чтобы люди захотели платить вам за нее, и достаточно доброжелательной, чтобы вам не приходилось скрывать, что она делает.

person zwol    schedule 30.08.2018

Мне нужно изменить код следующим образом. Кроме того, в Visual Studio есть важная опция компилятора, например, для отключения предотвращения выполнения данных.

Использованный параметр компилятора: /permissive- /GS /TC /GL /analyze- /W3 /Gy /Zc:wchar_t /Gm- /O2 /sdl /Zc:inline /fp:precise /Zp1 /D «_MBCS» /errorReport: подсказка / WX- / Zc: forScope / GR- / Gd / Oy- / Oi / MD / FC / nologo / диагностика: классическая

Используется параметр компоновщика: /MANIFEST /LTCG:incremental /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" /ИСПРАВЛЕНО /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();
}

Таким образом я смог сначала расшифровать сегмент, а затем выполнить функцию.

person Luca Reccia    schedule 12.09.2018