需要 C 编译器选项来创建易于反转的可执行文件来教授反转
Posted
技术标签:
【中文标题】需要 C 编译器选项来创建易于反转的可执行文件来教授反转【英文标题】:Need C compiler options to create to easy-to-reverse executable to teach reversing 【发布时间】:2017-01-21 10:38:59 【问题描述】:我编写了一个简单的 C 程序,目的是让学生使用 OllyDbg 对其进行反转和修补以更改其执行方式。他们只需要找到 3 并将其更改为 5。编译的可执行文件充满了难以理解的启动调用,这将阻碍新手在 Olly 中扭转它的努力。我想告诉编译器删除所有/大部分内容。
我正在使用 Visual Studio 2015 Pro,但我不是 VS 高手,我不知道从哪里开始。
【问题讨论】:
好吧,我假设这些“启动调用”对于使您的程序执行非常重要。也许您应该考虑为更简单的目标进行编译,而不是尝试将它们剥离出来?用于小型嵌入式设备(如 AVR)的工具链可能会生成更简单的程序集。此外,如果您使用的是 GCC,则可以关闭优化 (-O0),这也有助于生成代码的可读性。 【参考方案1】:只要您的 main 函数不访问标准 C 库并且您只使用 Windows API 调用,您就可以使用以下两个链接器开关删除 c-runtime 启动代码:
/entry:<your_main_function> /nodefaultlib
在一个使用简单控制台应用程序(我假设您正在使用)和“main”主函数的完整示例中,您可以编译和链接您的代码没有 c-runtime库如下:
cl /c main.c
link /entry:main /nodefaultlib /libpath:<path_to_libs> /subsystem:console main.obj kernel32.lib user32.lib
如果您不想手动运行命令行工具,Visual Studio 会将等效选项隐藏在您的项目对话框中。
这应该会生成一个小而简单的 EXE。当你的调试会话开始时,你应该在你的 main 函数中开始。
注意:缺少标准 IO 可能会使输出数字(我假设您正在这样做)变得更加困难,因为您可能需要自己编写一些例程,例如获取字符串长度。但是,您需要输出到控制台的唯一 API 调用是 kernel32 GetStdHandle() 和 WriteConsole() 函数。请记住,在 user32.lib 中可以访问一个 wsprintf() API,我还建议您使用它来保持您的示例准系统,但仍然允许您构建 c 样式的格式化字符串。使用 wsprintf() 将您的号码转换为输出提示/字符串,并使用 WriteConsole 将其发送到控制台。
更新:下面是一个示例 C 程序,它输出两个数字相加的结果,不需要标准 C 库和 CRT 启动代码。这是一个很好的逆向工程示例,可以更改其中一个数字以在命令行上获得不同的结果。
免责声明:我同意 wsprintf() 确实是一个 不安全 函数,因为它缺乏检查缓冲区大小,并且误用时会导致缓冲区溢出。仅在此处使用它是因为它内置在 Win32 API (user32.lib) 中,并且是一种将数字转换为字符串的快速方法,仅用于本示例。
据我所知,Windows 内置的唯一 C 样式格式化函数是该函数的 ANSI/WIDE 版本。 strsafe.lib 函数似乎依赖于标准库,否则我会使用它们。如果你知道有什么不同,请告诉我!因此,如果您不使用标准 C 库函数,我建议您编写自己的数字到字符串转换函数或使用其他人的。
#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);
【讨论】:
感谢@bytepointer,使用来自 kernel32 的 GetStdHandle() 和 WriteConsole() 函数,然后使用您提供的编译器/链接器选项正是我所需要的。生成的可执行文件很容易让学生在 Olly 中反转。还要感谢您稍后添加的 非常 不错的代码示例。我将你的标记为答案。以上是关于需要 C 编译器选项来创建易于反转的可执行文件来教授反转的主要内容,如果未能解决你的问题,请参考以下文章