2016-09-13 1 views
5

나는 학생들이 OllyDbg를 역순으로 사용하여 실행 방법을 변경하도록 패치하는 목표를 가진 간단한 C 프로그램을 작성했습니다. 그들은 3을 찾아서 5로 바꾸면됩니다. 컴파일 된 실행 파일은 신생 기업이 Olly에서이를 뒤집을 수있는 노력을 방해하는 어려운 시작 호출로 가득 차 있습니다. 컴파일러에게 전부/대부분을 제거하라고 말하고 싶습니다.반전을 쉽게 할 수있는 실행 파일을 만들려면 C 컴파일러 옵션이 필요합니다.

저는 Visual Studio 2015 Pro를 사용하고 있습니다.하지만 VS Whiz가 아니기 때문에 어디서부터 시작해야할지 모르겠습니다.

+1

글쎄,이 "시작 호출"은 프로그램을 실행하는 데 매우 중요하다고 가정합니다. 어쩌면 그 (것)들을 밖으로 벗기는 것을 시도하기보다는, 더 간단한 목표를 위해 컴파일에 대하여 생각해야 하는가? 작은 임베디드 장치 (AVR과 같은)를위한 툴체인은 조금 더 간단한 어셈블리를 생성 할 수 있습니다. 또한 GCC를 사용하는 경우 최적화를 해제 (-O0)하여 생성 된 코드의 가독성을 높일 수 있습니다. –

답변

3

만큼 주요 기능은 표준 C 라이브러리에 접근하지 않고 당신은 단지 당신이 다음과 같은 두 가지 링커 스위치와 C-런타임 시작 코드를 제거 할 수 있습니다, 윈도우 API 호출을 사용할 때 :

/entry:<your_main_function> /nodefaultlib 

를 A의 당신이 컴파일하고 다음과 같이없이 C-런타임 라이브러리 코드 를 연결할 수있는 간단한 콘솔 응용 프로그램 (난 당신이 사용하는 가정 한한다)와 "주"의 주요 기능을 사용하여 전체 예제 :

cl /c main.c 
link /entry:main /nodefaultlib /libpath:<path_to_libs> /subsystem:console main.obj kernel32.lib user32.lib 

비스 수동으로 명령 줄 도구를 실행하지 않으려면 Studio 대화 상자에 동일한 옵션이 있습니다.

이렇게하면 작지만 단순한 EXE가 생성됩니다. 디버깅 세션이 시작되면 주 기능에서 바로 시작해야합니다.

참고 : 표준 IO가 없으면 문자열 길이를 가져 오는 것과 같이 사용자가 직접 루틴을 작성해야하므로 숫자를 출력하는 것이 어려울 수 있습니다. 그러나 kernel32 GetStdHandle() 및 WriteConsole() 함수 만 콘솔에 출력해야합니다. userb.lib에서 액세스 할 수있는 wsprintf() API도 있습니다.이 API는 샘플 베어 본을 유지하면서 C 스타일의 서식 지정된 문자열을 작성할 수 있도록하는 것이 좋습니다. wsprintf()를 사용하여 숫자를 출력 프롬프트/문자열로 변환하고 WriteConsole을 사용하여 콘솔에 전송하십시오.

업데이트 : 다음은 표준 C 라이브러리 및 CRT 시작 코드없이 두 개의 숫자를 더한 결과를 출력하는 샘플 C 프로그램입니다. 이것은 명령 행에서 다른 결과를 얻기 위해 숫자 중 하나를 변경하는 좋은 역 엔지니어링 샘플입니다.

면책 조항 : 저는 wsprintf()가 실제로 안전하지 않은이라는 점에 동의합니다. 버퍼 크기 검사가 부족하고 잘못된 사용으로 인해 버퍼 오버플로가 발생할 수 있기 때문입니다. 여기서는 Win32 API (user32.lib)에 내장되어 있기 때문에 여기에서만 사용되며 숫자를이 예제의 문자열로 변환하는 빠른 방법입니다.

내가 아는 한, Windows에 내장 된 유일한 C 스타일 서식 기능은이 기능의 ANSI/WIDE 버전입니다. strsafe.lib 함수는 표준 라이브러리에 의존성이있는 것 같습니다. 그렇지 않으면 사용했을 것입니다. 다른 점을 알고 계시면 알려 주시기 바랍니다. 따라서 표준 변환 함수를 사용하지 않으면 문자열 변환 함수에 고유 한 숫자를 쓰거나 다른 사람이 사용하는 것이 좋습니다.

#include <Windows.h> 

//quick-and-dirty string-length function 
DWORD getStringLen(const char* pszStr) 
{ 
    const char* p = pszStr; 
    while(*p) ++p; 
    return(p - pszStr); 
} 

//program entry point - note that int return value does propagate back to 
// ExitProcess() despite main() being the program's actual entry point; 
// the ret at the end of this function returns back to the loader, which 
// in turn calls ExitThread() with EAX; the return value can be 
// checked on the comamnd-line via: echo %ERRORLEVEL% 
int main(void) 
{ 
    DWORD dwNum1 = 5; 
    DWORD dwNum2 = 3; 
    DWORD dwResult = dwNum1+dwNum2; 

    //build formatted output string 
    // 
    // NOTE: wsprintfA() is an unsafe function and is only used as an example 
    //  DO NOT USE in production code! 
    // 
    #pragma warning(disable : 4995) //wsprintf is a depreciated function 
    char szTemp[100]; 
    int iRet = wsprintfA(szTemp,"%u + %u = %u\n",dwNum1,dwNum2,dwResult); 

    //get console stdandard output handle 
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); 
    if (INVALID_HANDLE_VALUE == hConsole) 
    { 
     iRet = -1; 
    } 
    else 
    { 
     //output the string 
     WriteConsoleA(hConsole,szTemp,getStringLen(szTemp),&dwNum1,NULL); 
    } 

    return(iRet); 
} 
+0

감사합니다 @bytepointer, kernel32의 GetStdHandle() 및 WriteConsole() 함수를 사용하고 컴파일러/링커 옵션을 사용하면 정확히 필요한 것입니다. 실행 파일은 학생이 Olly에서 쉽게 되돌릴 수 있도록 만들어졌습니다. 나중에 추가 한 멋진 코드 예제 **에 감사드립니다. 나는 너를 대답으로 표시하고있다. – mvwhyatt

관련 문제