`
hulianwang2014
  • 浏览: 757366 次
文章分类
社区版块
存档分类
最新评论
  • bcworld: 排版成这样,一点看的欲望都没有了
    jfinal

分析没有main的exe程序(一)

 
阅读更多
标题 分析没有main的exe程序(一)
关键字 CRT,C++,Windows sdk
出处 http://blog.csdn.net/heyangbin
第一部分:基础
1. 基本概念
我们平时接触VC++的时候,第一个接触到的恐怕是WinMain和main,对应于Win32子系统的Windows窗口系统和控制台两个部分,最多是某些书籍上谈到了对应多字节字符集的几个变种。其实,这几个入口点函数是VC++带有的C运行库要求的入口点。真正的vc程序的入口点函数是在使用VC++的C编译器编译程序时指定的。它可以是符合下面形式的任何名称的函数:
void __cdecl Your_Entry (void);
如果你喜欢,你可以起一个更加艺术的名字。
说到这里,给出一个样例程序可以更好的理解这个入口点函数和我们平时接触的C运行时入口点函数之间有些什么。这是一个什么都不做的程序
// VC++ Entry point
void MyEntry (void);
{
{
将这些个字符敲在一个文本文件中,保存为:d:/myentry.c
然后在VC++命令提示符环境中键入下面的步骤来编译、连接这个程序。如果没有注册环境变量则进入VC++的bin目录,缺省安装下,它应该在如下的目录中:
C:/Program files/Microsoft Visual Studio/VC98/Bin
然后运行vcvars32.bat批处理文件,如下图所示:
图略
屏幕会提示顺利设置了vc的环境变量。
l 然后用下面的命令编译上面的代码文件
d:/
cl /c myentry.c /nologo
(/c 编译生成obj不连接 /nologo 取消编译器编译期间的信息性消息显示)
如果没有什么提示而很快的出现命令提示符,则表示编译成功。
l 然后用下面的命令连接
link /ENTRY:"MyEntry" /OUT:myentry.exe /SUBSYSTEM:WINDOWS /NODEFAULTLIB myentry.obj /nologo
不出什么意外的话,在D分区上应该有一个myentry.exe文件,双击它发现什么也没有出现。但是,其实它是一个完整的Win32应用程序。
I 然后用下面命令测试
dumpbin /disasm myentry.exe
输出:
00401000: 55 push ebp
00401001: 8B ECmov ebp,esp
00401003: 33 C0xor eax,eax
00401005: 5D pop ebp
00401006: C3 ret
可以发现在入口点处是几个符合C函数调用规则的几个压栈、数据转移、和出栈指令。
上面用到的一些cl和link程序开关选项的意义请参考MSDN。
值得提一提的是:缺省情况下,link程序连接了4个C运行时库中的某一个,并且将函数mainCRTStartup、wmainCRTStartup、WinMainCRTStartup、wWinMainCRTStartup中的一个作为缺省的入口点(我们这里只讨论非动态连接库,也就是一般的可执行印象)。具体使用哪个,是根据link命令行中指定的子系统。可以参考MSDN获取更详细的说明。
2. Microsoft C/C++ Runtime Library
有了上面这些基础,我们接着再看一看Microsoft C/C++ Runtime Library在入口点处都作了些什么。我这里给出的代码是经过筛选的,只是为了说明问题,这些代码在VC安装目录中CRT/SRC下面的crt0.c中,缺省没有安装。
#undef _UNCODE
void WinMainCRTStartup (void)
{
int mainret;
STARTUPINFO StartupInfo;
_osver = GetVersion ();
_winminor = (osver >>8) & 0x00FF;
_winmajor = _osver & 0x00FF;
_winver = (winmajor << 8) + _winminor;
osver = (osver >> 16) & 0x00FFFF;
if (!_heap_init (1))
fast_error_exit (_RT_HEAPINIT);
_acmdln = (char*) GetCommandLineA ();
_aenvptr = (char*) __crtGetEnvironmentStringsA ();
_setargv ();
_setenvp ();
_cinit ();
StartupInfo.dwFlags = 0;
GetStartupInfo (&StartupInfo);
mainret = WinMain (GetModuleHandleA (NULL),
NULL,
;pszCommandLine,
StartupInfo.dwFlags & STARTF_USESHOWWINDOWS ?
StartupInfo.wShowWindow : SW_SHOWDEFAULT);
exit (mainret);
}
上面的代码经过筛选,它用于多线程下,普通的多字符集C运行时。我稍微解释一下代码的含义,它完成以下任务:
l 获取操作系统的版本信息,用于以后的操作;
l 然后初始化进程堆栈;
l 获取命令行,获取和设置环境变量;
l C运行时内部变量的初始化;
l 调用标准Win32窗口程序入口点函数(它应该是在你的应用程序中被定义和实现的);
l 调用ExitProcess函数退出应用程序,退出代码是WinMain的返回值。
具体的代码请参见运行库的源代码。
3. 不使用运行库编写自己的应用逻辑
接着,我们来试试看,不使用C运行库,并且使得我们的应用程序做些个事情。请看下面的代码:
// 程序init.c
#pragma once
#include <windows.h>
void entry (void)
{
char** p;
char* pAlloc;
char* pszNames[] = {
"SNK",
"Capcom",
"Nintindo",
"EA",
"3DO",
NULL
};
for (p = pszNames; *p != NULL; p ++)
{
MessageBox (0, *p, 0, MB_OK);
}
pAlloc = VirtualAlloc (0, 4096, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE);
if (pAlloc)
{
const char* pText = "Hello, world!";
char* pTemp = (char*) pText, *pstr = pAlloc;
for (;*pTemp != '/0';) *pstr++ = *pTemp++;
*pstr = *pTemp;
MessageBox (0, pAlloc, 0, MB_OK);
VirtualFree (pAlloc, 4096, MEM_RELEASE);
}
}
使用下面的命令行来编译连接它
cl init.c /c
link init.obj /SUBSYSTEM:WINDOWS /OUT:init.exe /ENTRY:”entry” /NODEFAULTLIB kernel32.lib user32.lib
生成的init.exe程序的运行中界面如下:
图略
这个程序打印一些名词后,调用基本服务中的虚拟内存分配函数,分配并且保留了4096字节的区域,然后将大家熟悉的一个字符串复制到其中,然后用窗口管理函数中的MessageBox函数输出屏幕对话框显示。它连接了kernel32.lib库和user32.lib库。没有C运行库的日子将是痛苦的,没有了malloc、拷贝字符象要受罪。但是,这是一个干净清爽的程序,没有拖泥带水。那些个嫌MFC拖沓累赘的朋友不妨自给自足,使用这个框架编写程序(-_-)。
4. 使用VC集成环境来编译上述程序
每一次编译上述应用程序都要在命令提示符中键入冗长的命令岂非是自虐。为此,我把在VC集成环境中编译它们的方法说一说。
使用VC的向导中Win32 Console Application项,生成一个空的工程,然后将init.c文件添加进去(不用说方法了吧)。
打开工程设置对话框:删除C/C++标签底部的文本框中除了/nologo /c两项的其它所有项目。删除link标签底部文本框中所有内容,将上述命令行中内容添加进去,除了init.obj。将输出目录改成想要的目录。接着用F7就可以编译连接了。
本文还有一个例子程序:不知道csdn如何上传文件,请知情的网友告知。
以后会介绍微软的C运行库,帮助大家熟悉Windows的一些基本服务。然后,时间允许的话,会写一个VC向导,自动生成上述代码的框架,并且提供一个简单的运行库。

分享到:
评论

相关推荐

    CustomPSourceP(0.99.28).zip_main.exe_source main.exe

    【标题】"CustomPSourceP(0.99.28).zip_main.exe_source main.exe" 指的是一款针对 "main.exe" 的定制化源代码包,版本号为0.99.28。在软件开发中,"source" 通常意味着程序的原始代码,也就是程序员编写的、未经过...

    matlab编写的程序打包发布生成exe的方法

    然而,在实际应用中,我们经常需要将 Matlab 编写的程序打包发布生成可执行文件(exe),以便在没有 Matlab 环境的机器上运行。下面将详细介绍 Matlab 编写的程序打包发布生成exe的方法。 方法一:使用命令行方法 ...

    一个EXE文件的启动过程

    在Windows操作系统中,一个`.exe`可执行文件的启动过程是一个复杂且有序的系统级活动。这个过程涉及多个系统组件的交互,包括加载器、内存管理器、动态链接库(DLL)以及各种系统服务。以下是对这个过程的详细阐述:...

    java2exe(java打包为exe程序)

    Java2EXE是一种工具,它允许开发者将Java应用程序转换成Windows平台下的可执行文件(.exe),以便用户可以直接双击运行,而无需安装Java运行环境(JRE)。这对于那些希望简化部署过程,或者面向不熟悉Java环境的终端...

    tt端11.70.28可用的全汉化无壳的main.exe(解决爆卡问题)

    本文讨论的"tt端11.70.28可用的全汉化无壳的main.exe(解决爆卡问题)",是一个涉及游戏客户端更新的具体案例,它不仅表明了一个游戏版本的迭代,还反映出游戏优化和用户界面本地化的趋势。 首先,tt端这个名词可能...

    Hex文件查看器,解压运行里面main.exe文件即可,打开文件以16进制显示文件的内容。

    "解压运行里面main.exe文件即可"说明这是一个可执行的Windows程序,用户只需将压缩包解压后运行名为`main.exe`的文件,即可启动Hex查看器。 描述中提到的“无需安装,无需注册”,意味着这个Hex查看器是便携式的,...

    灰色预测模型exe程序.rar

    这个"灰色预测模型exe程序"压缩包包含了用于执行灰色预测及相关分析的可执行文件`main.exe`。下面我们将深入探讨灰色预测模型及其相关应用。 灰色预测模型(Grey Prediction Model,简称GM模型)由邓聚龙教授于20...

    实现对C程序设计语言的源程序(自定)的词法分析.zip

    该词法分析器能实现对自己输入的类C语言源程序中的所有单词进行分类,指出其所属类型,实现简单的词法分析操作。需解压后打开Microsoft Visual Studio运行,或者直接打开词法分析\词法分析\Debug文件夹里面的.exe...

    使用flex编写一个词法分析器

    我们可以使用flex语言编写一个词法分析器,然后使用flex.exe对其进行编译,得到一个C语言的源代码文件,该文件可以被编译成一个可执行文件,以便进行词法分析。 在这个实验中,我们定义了三个词法单元:INTEGER、ID...

    CreateProcess拦截exe程序

    在这个场景中,"CreateProcess拦截exe程序"指的是通过API Hook来拦截`CreateProcess`函数,这是一种Windows API,用于创建新的进程和其初始线程。下面我们将深入探讨`CreateProcess`、API Hook的基本概念以及如何...

    IDA pro逆向工具的使用以及逆向分析程序实例操作

    6.附带4个解密案例程序,包括三个exe文件和一个linux程序的逆向实操 环境: IDA pro7.6, linux, vc++ 适合人群: 具备一定编程基础,作业时间不够的学生,ida初学者 阅读建议: IDA pro逆向工具的初步入门,此...

    Java打包程序转换为 windows exe

    3. **嵌入Java运行时**:JSmooth会自动检测用户的系统是否已安装Java,并根据需要内置一个轻量级的Java运行时环境,确保程序在没有Java环境的机器上也能运行。 4. **生成EXE文件**:结合分析结果和配置文件,...

    DOS软件EXE2BIN的C源程序代码

    在DOS操作系统环境中,"EXE2BIN"是一个经典的实用工具,它能够将可执行的.EXE文件转换成纯二进制的.BIN文件。这种转换有时在处理低级磁盘映像、创建启动盘或者进行其他需要原始二进制数据的场景中是必要的。本文将...

    利用LEX自动生成词法分析程序

    编写一个LEX源程序,使之生成一个词法分析器,能够输入的源程序转换为单词序列输出。 三、实验环境 Flex+VC6.0 四、实验注意 1.Id正则表达式:{letter}({letter}|{digit})* 2.Num正则表达式:{digit}+(\.{digit}+)...

    JAVA程序打包成exe文件

    **exe4j**是由Ejel Technology开发的一款强大的Java应用程序打包工具,它可以将Java程序及其依赖项打包成一个独立的Windows可执行文件(.exe)。这样,用户无需安装Java环境即可直接运行程序。 - **准备工作**: -...

    MainCode Decrypter samsat F1 by zamoranoss

    【标题】"MainCode Decrypter samsat F1 by zamoranoss" 是一个由用户zamoranoss创建的程序,主要用于解密特定类型的代码,特别是与samsat相关的编码。这里的“F1”可能指的是该工具的一个版本或功能标识。 【描述...

    恶意ChatGPT应用程序分析报告

    7. **.NET框架分析**:"setup.exe"是一个.NET编写的程序,通过dnSpy反编译工具可以查看其源代码结构。 8. **程序入口点**:虽然在main函数中没有发现直接的资源释放操作,但在main函数执行之前,有额外的代码被执行...

    exe4j打包软件

    这样,即便目标计算机没有安装Java运行环境,程序也能正常运行,因为exe4j会自动包含必要的JRE组件。 2. **多配置支持**:exe4j支持创建多个执行配置,针对不同的需求和环境设置不同的启动参数和选项,如最小化的...

    一个exe可执行文件的生与死(运行原理)

    #### 二、exe程序的初始化 ##### 1. **双击exe文件** 在用户界面中,双击exe文件的动作被Shell(以Explorer.exe进程的形式实现)捕获。当用户启动计算机并进入桌面时,操作系统会自动启动Explorer.exe进程,而其他...

    一种CPU占用过高的故障定位分析方法

     CPU占用过高是LINUX服务器出现常见的一种故障,也是程序员线上排查错误必须掌握的技能,我们经常需要找出相应的应用程序并快速地定位程序中的具体代码行数,本文将介绍一种CPU占用过高的一种处理思路,文中采用四...

Global site tag (gtag.js) - Google Analytics