专栏首页离别歌 - 信息安全与代码审计[普及]程序自启动方式 - ActiveX

[普及]程序自启动方式 - ActiveX

[普及]程序自启动方式 - ActiveX

    每次都是一个假期不开VC,可能都是在学校做的多了,回家了要换个口味。

    已经在学校呆了好几天,明天还要补考,想着想着就泪流满面了。正逢着大一新生到来的时间,我也想到了去年自己刚坐在这所学校的课堂里时,那份激动与不安。也是那时候,我写了我人生第一个Widnows程序,也就此跟VC结下了不解之缘。

    当时写的东西是“编程实现自启动”。当时还是懵懂初开,查了不少资料,写了一个基于修改注册表实现的自启动。实现自启动的方式还有很多,当时再就没有继续深入了。

    于是,在这一周年之际,我来继续完成我当年没有完成的任务。    


    这次先来个低烈度的,ActiveX自启动,基本也是通过修改注册表某个键值来达到自启动的效果。

    拿来开刀的是类似这个键:HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Active Setup\\Installed Components\\{C9B4C1CD-B018-4511-B0A1-5476DBF70821}

    我们win+R 输入regedit启动注册表,找到该键。

    呵呵,当你找的时候可能就发现,你注册表中并没有这个键。其实{C9B4C1CD-B018-4511-B0A1-5476DBF70821}这串字符串是可以更改的,随便更换几个字符,只要是16进制允许的字符都可以。(格式xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)

    在该键下增加一个子键,键名为“StubPath”,键值为我们待启动的程序。

    还有一点要注意的,我们系统在第一次ActiveX自启动完成后,会生成一个键:HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Active Setup\\Installed Components\\{C9B4C1CD-B018-4511-B0A1-5476DBF70821}

    注意哟,它在根节点HKEY_CURRENT_USER下,名字和之前那个相同。当该键存在时,下次自启动就不会加载这个ActiveX了。

    所以我们编程时候要注意,每次启动起来后,删除掉该键,这样下次才能继续自启动。

    废话不多说,我写了一个小小的示例代码。

int WINAPI WinMain(
  HINSTANCE hInstance,      // handle to current instance
  HINSTANCE hPrevInstance,  // handle to previous instance
  LPSTR lpCmdLine,          // command line
  int nCmdShow              // show state
)
{
	HKEY hKey;
	DWORD dwDpt = REG_OPENED_EXISTING_KEY;
	long lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Active Setup\\Installed Components\\{C9B4C1CD-B018-4511-B0A1-5476DBF70821}",
		REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, &hKey);
	if (ERROR_SUCCESS != lRet)
	{
		char SelfFile[MAX_PATH];
		char SystemPath[MAX_PATH + 20];
		GetSystemDirectory(SystemPath, sizeof(SystemPath));
		strcat(SystemPath, "\\activexrun.exe");
		GetModuleFileName(NULL, SelfFile, MAX_PATH);
		CopyFile(SelfFile, SystemPath, FALSE);
		CreateStringReg(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Active Setup\\Installed Components\\{C9B4C1CD-B018-4511-B0A1-5476DBF70821}",
			"StubPath", SystemPath);
		return 0;		
	}
	MyCode();
	return 0;
}

    首先使用RegOpenKeyEx函数打开HKEY_LOCAL_MACHINE下的键,如果打开成功,返回ERROR_SUCCESS。

    这里判断其打开成功或失败的原因是,如果打开成功,说明有该键不存在,进一步说明这个程序是第一次自启动,这时我们就执行if语句中的内容。

    if中代码作用,就是把本程序拷贝进系统目录,并新建该键,以备下次启动。

    其中有一个函数,CreateStringReg是我自己定义的。这个函数在这里就是创建一个键名为StubPath的子键,其值是我们需要自启动的程序的绝对地址。

//修改或创建字符串类型的键值
void CreateStringReg(HKEY hRoot, char *szSubkey, char * ValueName, char *Data)
{
	HKEY hKey; 
	long lRet = RegCreateKeyEx(hRoot, szSubkey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL);
	if (ERROR_SUCCESS != lRet)
	{
		//TRACE("error on RegCreateKeyEx: %s\n", szSubkey);
		return ;
	}
	//修改或创建注册表键值
	lRet = RegSetValueEx(hKey, ValueName, 0, REG_SZ, (BYTE *)Data, strlen(Data));
	if (ERROR_SUCCESS != lRet)
	{
		//TRACE("error on RegSetValueEx: %s\n", ValueName);
		return ;
	}
	RegCloseKey(hKey);
}

    最后,我们的代码在MyCode函数中。这个其实都可以扩展了,我们可以开启一个线程,或者把代码注入到其他进程中。

    我的MyCode()函数很简单:

void MyCode(){
	WinExec("C:\\windows\\system32\\calc.exe", SW_SHOWDEFAULT);
	WinExec("C:\\windows\\system32\\start.bat", SW_HIDE);
}

    第一行是打开一个计算器。

    第二行很重要,是我写的一个批处理。我之前说到了,第一次ActiveX自启动成功后,会在HKEY_CURRENT_USER生成一个键:\\SOFTWARE\\Microsoft\\Active Setup\\Installed Components\\{C9B4C1CD-B018-4511-B0A1-5476DBF70821}。这个键直接导致下次不会再次自启动,所以我们每次自启动的时候要删除该键。

    start.bat:

reg delete "HKEY_CURRENT_USER\Software\Microsoft\Active Setup\Installed Components\{C9B4C1CD-B018-4511-B0A1-5476DBF70821}" /f

    原本我是预备在这个程序中删除该键的,但是试了很多次都没有成功。我估计原因是这样,第一次程序自启动成功后,在程序结束运行的时候系统才新建这个键。所以我程序中删除该键的时候,该键其实并不存在。所以,我只好调用一个外部程序(.bat),来删除这个讨厌的键。

    这只是一个简单的例子,可以删除这个键的方法还有很多,比如我们把代码注入explorer进程中,利用explorer来删除这个键。


最后说一个小技巧,如何缩小可执行程序的体积。

    以前我一直抵触用VC6写程序,过了很久我才明白很多木马用VC6的原因:缩小体积。

    VS2010中,在编译的时候会加入很多乱七八糟的编译选项,导致生成物体积庞大。而VC6顾虑没有这么多,所以生成的可执行文件体积小。gh0st为什么把客户端和服务端分开编写的原因我也顿悟了,被控端放在VC6下编译,而主控端没有大小要求就放在VS2010下编译。

    还有一个小文件Tiny.h,大家把他include进你的程序最上面,它能极大地减小编译完成后的体积:

/***************
* Leavesongs.com
* By phith0n
****************/
#ifdef NDEBUG 
#pragma optimize("gsy", on)

#pragma comment(linker, "/RELEASE")
#ifdef _MERGE_RDATA_
#pragma comment(linker, "/merge:.rdata=.data")
#endif
#pragma comment(linker, "/merge:.text=.data")
#pragma comment(linker, "/merge:.reloc=.data")
#if _MSC_VER >= 1000
#endif
#endif

#pragma comment(linker, "/ENTRY:WinMain")
#pragma comment(linker, "/MERGE:.rdata=.data")
#pragma comment(linker, "/MERGE:.text=.data")
#pragma comment(lib, "msvcrt.lib")
#if (_MSC_VER < 1300)
	#pragma comment(linker, "/IGNORE:4078")
	#pragma comment(linker, "/OPT:NOWIN98")
#endif
#define WIN32_LEAN_AND_MEAN

    可能有些地方还需要根据情况修改,倒数第9行的WinMain是入口点函数,大家要酌情修改。

    在没有include<tiny.h>时,编译好的程序有16k左右,而包含了该头后,程序只有1.50k了。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • ngx_lua_waf针对性改写

    当初选择ngx_lua_waf作为自己的WAF,主要原因就是因为其可扩展性与性能上有一个很好的平衡。

    phith0n
  • 创造tips的秘籍——PHP回调后门

    最近很多人分享一些过狗过盾的一句话,但无非是用各种方法去构造一些动态函数,比如_GET['func'](_REQUEST['pass'])之类的方法。万变不离其...

    phith0n
  • 一个前端DOMXSS过滤器

        最近热衷于刷twitter,各种大牛的东西让我应接不暇,感觉确实新有干货,前几天看到Yosuke发状态了:

    phith0n
  • SAP Kyma上kyma-system命名空间下的pod列表

    版权声明:署名,允许他人基于本文进行创作,且必须基于与原先许可协议相同的许可协议分发本文 (Creative Commons)

    Jerry Wang
  • nginx工程师,需要上承天命,下召九幽

    nginx很好用,几乎每个公司都在用,它的功能主要有 反向代理、 负载均衡、 动静分离等,其中最主要的就是反向代理。

    xjjdog
  • 腾讯云CVM公网网络带宽上限说明

    我们设置的公网网络带宽上限默认为出网带宽上限,即从 CVM 流出的带宽。公网网络的带宽上限根据不同的网络计费模式有所不同。具体信息如下:

    网络带宽
  • python | 解决defaults::qt-5.6.2-vc14_3

    解决方案: 在目录:E:\Anaconda3\Lib\site-packages\conda\common下修改compat.py

    努力在北京混出人样
  • 投资中的那些坑:幸存者偏误

    >韭菜并没有真正的认识到市场真实的样子,只是被表面现象迷惑,用自己以为的想法,再加上本能冲动进行操作。

    凌帅出口
  • Android回调接口的写法

    六月的雨
  • 拨打18687679495_缅甸小勐拉银河国际开户Redis为什么这么快

    Redis是一个开源的内存中的数据结构存储系统,它可以用作:数据库、缓存和消息中间件。

    我是你的眼晶

扫码关注云+社区

领取腾讯云代金券