关于QQ

1)--- 转载自水木清华BBS

发信人: Christopher(三少爷)

信区: Hacker

标 题: 修改QQ2000b(Build 0710)的广告窗口

发信站: BBS 水木清华站 (Sun Dec 2 14:52:45 2001)

最近的QQ2000b(Build 0710)好像多了个新功能,广告都用专门的 弹出窗口来播放。本来也没什么,免费的

东东,总得让人家腾讯活下去啊,放点广告赚点银子也是为了更好的为大家服务嘛。不过窗口打开就不让人关

上,“逼”着你非得看完一遍广告就不对了,总得让人有不看的自由吧?所以我就小试水果刀一把,在QQ的

Exe文件上动了一点小手脚,让这个广告窗口能蹦出来,但是也能让我不想看随时可以关闭它。首先,我们要

有一些工具来做这件事。我先找了个ExeScope来看QQ的资源(实在不行用VC),找到那个广告窗口的对话框

资源(有点费劲)ID号是804(0x324),而且从这些资源编辑器里还能看出那个“关闭” 按钮(ID号是2)缺

省并不是Disabled,这说明是在程序里用GetDlgItem加EnableWindow使这个按钮不可按下的。找到这个线索就

好办了。然后找一个反汇编工具,一定是能分析Windows API调用的那种(比如wasm)。然后在分析结果里查

找关键字“GetDlgItem”,还好,这个调用不是很多,而且最重要的是要看在这个“call”指令之前“push”

了什么东西进栈(因为这就是调用参数)。我们站在一般的程序员的角度想一想,要Disable一个按钮,当然

先要得到它的窗口句柄,所以要调用GetDlgItem参数一个是父窗口句柄(这个我们不关心),一个就是按钮的

ID。我们已经查到是2了,所以只要看各个GetDlgItem调用之前倒数第二个push进栈的是不是2就可以了。也许

有人会说难道一定要用立即数寻址吗?不能把ID号存在一个局部变量里吗?我说,你还是要站在VC程序员的角

度想想,一个按钮的ID当然是用资源编辑器生成的宏(被翻译 成立即数)来代替最方便了,谁也不会这么变

态非要先赋值再使用吧?很快我们就找到这个调用GetDlgItem的地方了,参数也是2,而且再往下几行就是调

用IsWindowEnabled,以及调用SendMessage。这个逻辑已经很清楚了, 先是找到这个按钮的句柄,然后判断

是否已经被Disable了(当然肯定还没有, 真是多此一举)如果已经被Disable了就跳到51F3D9去,没有的话

继续往下执行SendMessage,很明显,这个SendMessage就是要广告窗口的窗口过程Disable那个关闭按钮了。

所以,我们只要在IsWindowEnabled调用后的判断、跳转语句上做点文章就可以了。原来的程序用的是

je 51F3D9(74 17),用二进制文件编辑器UltraEdit把它改成jmp 51F3D9(对应的二进制代码是EB 17)。然

后存盘,一切搞定!现在,虽然也弹出广告窗口,但是我可以选择继续看还是马上把它关闭了,就这么简单!

 

2)--- 转载自邹丹的主页(www.zoudan.com)

为OICQ 820添加显示IP地址和端口号的功能

特别申明:本文所述的内容仅供研究交流之用,如用作非法用途或修改不当,一切后果自负!

作者:邹丹

电邮:tpo@sina.com

主页:http://www.zoudan.com

注意:只适合OICQ 0820C版本。

我们的目标是去掉广告显示,并且在广告的位置上显示目标对象的IP地址和端口号。我们应该怎么下手呢,好

的,慢慢跟我来!经过对Oicq目录结构的分析,发现目录AD和广告有关。其一是广告的英文简写就是AD,其二

是其中的图片文件就是我们在广告中看到的。试着删除该目录之后,呵呵,广告消逝了。但是下次进入Oicq之

后,程序会自动新建这个目录,并且重新下载广告文件。既然程序读取不到广告文件广告就会消失,那么就人

工让它读不到。用Soft-ice把断点设置在CreateFileA上,这个API调用一般是用来打开一个文件或者设备的。

在Sice截到断点后,查看是即将打开的那些文件,从而判断是否是我们要修改的地方。具体修改方法详见“打

开广告文件的程序段”。广告是去掉了,但是在广告区域上点击鼠标,浏览器仍然会打开广告链接,看来我们

还需要对程序作更完善的修改。好了,既然点击广告会出现浏览器,那一定是运行了一个程序。一般打开运行

浏览器程序的有两种方法,一是调用COM接口,二是调用普通的运行程序的API函数。第一种方法技术难度高,

一般程序很 少采用。所以直接用Sice把断点设置在几个和运行程序有关的API函数上,比如ShellExecuteA,

WinExec等等。好了,程序在ShellExecuteA处中断,也就是只要避过这个API函 数就行。呵呵,顺着程序往上

找合适的修改位置,会发现USER32.PtInRect函数的调用,经过分析,发现它是用作判断鼠标点击是否在特定

区域内的。搞定,只要使它判断总是在区域外,就不会执行到ShellExecuteA那儿去了。发送消息窗口和回复

窗口的广告点击的程序在不同的位置,也就说在两个地方,这两个地方都要修改,原理也都是一样。具体修改

方法详见“发送消息窗口点击广告的程序段”和“回复消息窗口点击广告的程序段”。(我们为了实现在点击

鼠标后出现IP地址和端口号,在发送消息窗口添加了一个有关显示的程序入口,我将在后面讲解)。这下广告

真的是去除了,既不能看到,也不能点进去了。呵呵,开始我们的下一步目标,显示IP地址和端口号!!!过

去要想知道Oicq上朋友的IP地址只有借助民间的一些小工具程序或者采用包监听程序,后者专业要求比较高,

而且辨别率低,也不方便。一些小程序的确很管用,但是毕竟没有把这个功能直接做到Oicq程序上方便可靠,

利用Oicq内部的很多数据和结构能获得很多我们平常不容易获得的信息。但是毕竟只有二进制汇编代码,没有

源程序,程序的分析难度和工作量可想而知。经过令人难以想象多次数的死机和重起,以及极其艰辛的设置断

点跟踪调试分析工作……(以下省略5201314字),终于粗略的获得了我们感兴趣的数据结构指针以及它相关

调用的位置。这段时间是我最郁闷的时候,想起那段毫无人性的工作,就像已经过上幸福生活的老同志回忆起

1949年以前悲惨生活般的胆战心惊且心有余悸……(以下省略520字)。还好我挺过来了,终于在0042513D处

找到了需要的指针地址。只要利用这个指针就能获得目标对象的IP地址以及端口号。我们需要做的就是把这些

信息显示在以前的广告位置。又是一项艰巨的任务放在我的面前,还好我有坚定的信念、丰富的临床经验以及

对成功喜悦的企盼,还有对聊天MM住址的渴望,我一定会珍惜,不能像周星星一样期望再来一次……(再次省

略若干,以免挨鸡蛋)。言归正传,既然获得了关键的数据指针,那可以说我们已经成功了90%了,接下来的

就是显示出来而已。但这也需要反复的试验和修改。让我们好好来回味一下这一过程: 首先,要实现新的功

能毫无疑问需要添加代码和数据,以及执行一定的API函数,所以要找到适当的方法添加代码到原程序之中。

完美的方法就是作一个外壳添加程序,在原程序中添加所需要的段(数据段,程序段),以及添加Import表表

项,以用于新的API函数的地址定位,还要修改PE文件头中的各项相关信息,这就是病毒的做法。这无疑非常

的复杂和繁琐,有兴趣的同学可以参见我以前的文章“关于95下可执行文件的加密研究”。其实我们的要添加

的程序量并不大,充其量也就零零星星的几百个字节,而且用到的API函数也不多。所以我们采取了手动修改

添加的方法,但也需要必要的条件和方法。看我以下的分析和方法: PE可执行文件的逻辑结构是段,比如代

码段“.text”、数据段“.data”、资源段“.rscs”等等。这些段大小都是按文件对齐,也就是说段大小至

少会按10h对齐,一般是1000h(4096字节),这由文件头中指定(链接的时候确定)。但代码也好数据也好,

不可能做到长度刚好是对齐的。也就是说,段的大小是大于段中代码或数据实际大小的。他们之间的差值就是

该段冗余的空间,这个空间被称为“空隙”。有一些简单的PE文件减肥软件就是使用去掉“空隙”的方法来减

肥的。这个“空隙”可以被我们用来放置代码、数据以及堆栈。我常用的分析PE文件文件头的工具软件是

Borland以前在C++系列软件中带的“Tdump.exe”。让我们看看实际分析的结果:

Object table:

# Name VirtSize RVA PhysSize Phys off Flags

-- -------- -------- -------- -------- -------- --------

01 .text 000D0637 00001000 000D1000 00001000 60000020 [CER]

02 .rdata 000320E8 000D2000 00033000 000D2000 40000040 [IR]

03 .data 00039848 00105000 00012000 00105000 C0000040 [IRW]

04 .rsrc 0003E4C0 0013F000 0003F000 00117000 40000040 [IR]

以上是用Tdump看到的Oicq.exe的段信息(它的Oject就是我们所说的段)。我们肯定是首选.text段进行观察

(.text是代码段,Flag为CER,意思就是包含代码、可执行、可读的意思(Contains code,Execute,

Readable))。可以看到,.text段代码实际长度D0637h,物理长度D1000h,文件偏移位置为1000h处。OK,这

个段有D1000h-D0637h=C9Ch的“空隙”。这个长度完全可以满足我们的需要了,而且代码数据堆栈都可以放

在这个区域内。众所周知,要作为数据段使用,段的属性(Flags)需要可写。 好了,只需要改写“.text”

的属性即可,可写属性的值是80000000h,然后加上原来的60000020h后,就是C0000020h了,也就是变成了

CERW属性(具体修改方法详见“代码段段属性修改”)。看看我们更改后的用Tdump分析的结果。

Object table:

# Name VirtSize RVA PhysSize Phys off Flags

-- -------- -------- -------- -------- -------- --------

01 .text 000D0637 00001000 000D1000 00001000 C0000020 [CRW]

02 .rdata 000320E8 000D2000 00033000 000D2000 40000040 [IR]

03 .data 00039848 00105000 00012000 00105000 C0000040 [IRW]

04 .rsrc 0003E4C0 0013F000 0003F000 00117000 40000040 [IR]

好了,找到了放置代码数据和堆栈的地方,也就是其实偏移1000h+D0637h的地方。为了对齐边界,我们采用

D1640h这个值(文件偏移)。用Tdump查看代码段基址(Code Base)和PE文件映象基址(Image Base),分别

是1000h和400000h,可以算出我们的程序在装入后的实际地址,400000h+1000h+D0640h=4D1640h。也就是说我

们的代码在被系统装入后在内存4D1640h处,这在以后程序跳转处用到。添加代码的工作已经做好,现在关键

的问题就是编制具体的代码,以用于IP地址和端口号的保存和显示。首先是对对象数据中IP地址和端口信息的

保存,我们在获得该数据指针后(程序00425157处),更改程序使程序直接跳转到我们的保存程序中

(4D1640h)。该数据的指针首址放在EAX,由于该段程序有些寄存器的值都有用,堆栈也不能乱压。所以我们

首先修改了栈指针,使所有的堆栈活动都在我们的“空隙”中进行(堆栈顶端4D1900h)。然后保存几个寄存

器的值(压栈)。IP地址和端口号分别在该数据结构+214h和+218h的地方(也就是EAX+214h和EAX+218h)。

IP地址是一个字符串指针,端口是个32位整数。我们要做的是把他们都转换成字符串,保存在自己的地盘中。

我们巧妙的用了一个wsprintfA函数把字符串和端口号输出到一个地址上(随便在我们的“空隙”中找个空闲

的地址,我用的是4D1700h,4D1720h中放的是格式化字符串“%s:%d”)。实际这段程序翻译成C语言就是

printf(“%s:%d”,char *ip,int port),这样,我们就把字符串形式的数据保存在了数据区里。值得注

意的是,由于我们修改了原程序中的有用的代码用于跳转程序,所以在我们的程序中就需要加上

(cmp dword ptr [eax+000001DC], ecx)这句代码,退出我们的程序之前恢复栈指针和各寄存器,用一条无

条件跳转指令转回到原程序继续执行。细心的同学可能注意到我们没有显式的调用wsprintfA函数,但是我们

实际上是调用了。在显示IP的那段附加程序中调用SetWindowTextA的调用也是这样。这是怎么回事呢?我们知

道所有API函数的调用前都需要重定位,这个过程发生在系统装入这个PE程序的时候。系统按照PE文件中

Import表的内容对API函数在程序中的地址进行填写。我们没有修改Import表,所以,如直接写上汇编代码,

系统是不会为它定位的。由于Import表比较复杂,更改它是个非常繁琐的事情。所以我们采用变通的方法,既

然系统为用到的API函数地址都作了重定位,所以API函数的地址信息也就存在了。具体的做法如下:

找到原程序中有调用wsprintfA的地方:

:0049CE30 FF1560274D00 Call USER32.wsprintfA

:0049CE36 83C410 add esp, 00000010

:0049CE39 EB1A jmp 0049CE55

实际的汇编代码应该是Call dword ptr [004D2760],我们就知道wsprintfA的地址是放在004D2760中。所以,

我们只要间接的获得这个调用的地址,这个地址就是指向wsprintfA实际地址的二重指针。这样我们就可以直

接Call这个地址了。在“显示IP地址和串口的附加程序”中所用到的SetWindowTextA也是用这种方法调用的。

(具体修改方法见“弹出发送消息窗口之前的对象数据调用的程序段”和“保存IP地址和端口的附加程序”)

在把IP地址和端口保存为了字符串形式在4D1700h之后,今后只需要在需要的时候显示出来就行了。前面我们

提到了需要在点击广告后显示IP地址。所以,我们在点击广告的程序段中间添加了跳转到我们显示程序的入口

(4D1680h)。显示程序的原理很简单,使用SetWindowTextA函数把保存在4D1700h的字符串显示在以前广告的

窗口中。在显示之前,判断一下如果没有IP地址的情况,如果是只有一个冒号,说明没有IP地址,就简单的写

上一个“0”。调用SetWindowTextA函数的方法在前面已经提到。需要注意还有两个重要的问题:我们从什么

地方获得SetWindowTextA函数需要的一个参数――广告窗口句柄呢?我特意在“发送消息窗口点击广告的程序

段”中写出了在点击广告时有一个Call USER32.GetWindowRect调用的代码,这个函数同样需要窗口句柄。

[ESI+160h]就是USER32.GetWindowRect需要的广告窗口句柄,我们就可以利用这个句柄调用SetWindowTextA,

使字符串显示在广告窗口上。还有就是由于原来的广告窗口是用于图片的显示,所以不能用来显示字符。它的

窗口样式中有个SS_ETCHEDFRAME的值。我们需要去掉它并加上用于垂直居中和水平居中的两个样式SS_CENTER

和SS_CENTERIMAGE。一般静态对话框中的窗口元素(控件)都是静态的保存在资源段中,而不是程序动态生成

的。所以我们不需要改程序,只需要改掉资源段中的值就可以了。具体改法详见“消息发送对话框中广告窗口

样式的更改”。程序基本上改完了,终于可以享受我们辛苦改动的结果了,不料Oicq 820版有检查文件是否被

修改过这一手。同样,阻止我们通向成功道路上的任何障碍只能无情的被我们消灭,这个提示文件已被修改的

对话框也只能被我们搞掉。幸好搞它非常的简单,把断点设置在MessageBoxA上,等蹦出断点后,查找前面的

代码,找到判断是否弹出对话框的代码并且无情的干掉,详见“弹出文件修改警告框的程序段”。大功告成!

学到不少东西吧!这么多代码自己慢慢用UltraEdit查找修改吧,知道敲错一个的后果吗?呵呵,不是死机就

是重起。考虑到一些初级DIY用户的需求,我把修改好的EXE文件用专业的Patch软件“CodeFusion”作成了一

个18K的Patch执行文件。需要的朋友可以到我主页上去下载。(应腾讯公司要求,已撤掉该补丁程序,非常抱

歉)。好了,课程结束。如果有时间的话,还可以对Oicq作很多的改造。无疑这个任务是非常艰巨而复杂的,

但是只要你有必胜的信心以及充沛的精力,并且敢于接受这种毫无人性任务的挑战,还有视一切PPMM为粪土的

高尚眼光和能忍受对自己无情虐待的勇气,你会成功的!(¥……#%%……※#!¥#%啊啊啊啊~~~~

~~~呃~~,被前排学生暴扁)。~~~~下课咯~~~~

打开广告文件的程序段:

更改以前:

:0042AF5B FF152C244D00 --- Call KERNEL32.CreateFileA ;打开广告文件

:0042AF61 8BF8 --- mov edi, eax ;返回文件句柄

:0042AF63 83FFFF --- cmp edi, FFFFFFFF ;判断是不是无效句柄(打开失败)

:0042AF66 897D08 --- mov dword ptr [ebp+08], edi ;保存

:0042AF69 0F84EB000000 --- je 0042B05A ;无效就转

:0042AF6F 8D45F4 --- lea eax, dword ptr [ebp-0C]

:0042AF72 50 --- push eax

:0042AF73 57 --- push edi

更改以后:

:0042AF5B FF152C244D00 --- Call KERNEL32.CreateFileA ;打开广告文件

:0042AF61 8BF8 --- mov edi, eax ;返回文件句柄

:0042AF63 83FFFF --- cmp edi, FFFFFFFF ;判断是不是无效句柄(打开失败)

:0042AF66 897D08 --- mov dword ptr [ebp+08], edi ;保存

:0042AF69 E9CE000000 --- jmp 0042B03C ;不管打开成功与否都转

手工更改方法:

文件偏移:2AF69h

查找16进制代码:89 7D 08 0F 84 EB 00 00 00

更改为:89 7D 08 E9 CE 00 00 00 00

弹出文件修改警告框的程序段:

更改以前:

:00443B56 33FF --- xor edi, edi

:00443B58 397DDC --- cmp dword ptr [ebp-24], edi ;是否修改过原文件,是就弹出警告对话控件

:00443B5B 755C --- jne 00443BB9 ;不是转

更改以后:

:00443B56 33FF --- xor edi, edi

:00443B58 397DDC --- cmp dword ptr [ebp-24], edi

:00443B5B EB5C --- jmp 00443BB9 ;不管是不是都转

手工更改方法:

文件偏移:43B5Bh

查找16进制代码:39 7D DC 75 5C

更改为:39 7D DC EB 5C

发送消息窗口点击广告的程序段:

更改以前:

:00432B4E 50 --- push eax

:00432B4F FFB660010000 --- push dword ptr [esi+00000160] ;esi+160是窗口句柄

:00432B55 FF1578274D00 --- Call USER32.GetWindowRect

:00432B5B 8D45DC --- lea eax, dword ptr [ebp-24]

:00432B5E 8BCE --- mov ecx, esi

:00432B60 50 --- push eax

:00432B61 E8A6110700 --- call 004A3D0C

:00432B66 FF7510 --- push [ebp+10]

:00432B69 8D45DC --- lea eax, dword ptr [ebp-24]

:00432B6C FF750C --- push [ebp+0C]

:00432B6F 50 --- push eax

:00432B70 FF15B8274D00 --- Call USER32.PtInRect

:00432B76 85C0 --- test eax, eax ;判断是否在广告区域内点击

:00432B78 0F84FF000000 --- je 00432C7D

:00432B7E 6A10 --- push 00000010 ;是

:00432B80 FF157C274D00 --- Call USER32.GetKeyState

:00432B86 33DB --- xor ebx, ebx

:00432B88 663BC3 --- cmp ax, bx

:00432B8B 7D0F --- jge 00432B9C

:00432B8D C705D874510001000000 --- mov dword ptr [005174D8], 00000001

:00432B97 E9E8000000 --- jmp 00432C84

更改以后:

:00432B70 FF15B8274D00 --- Call USER32.PtInRect

:00432B76 85C0 --- test eax, eax

:00432B78 0F84FF000000 --- je 00432C7D ;判断是否在广告区域内点击

:00432B7E 6A10 --- push 00000010

:00432B80 FF157C274D00 --- Call USER32.GetKeyState

:00432B86 E9F5EA0900 --- jmp 004D1680 ;是就跳到我们的显示程序当中

:00432B8B 7D0F --- jge 00432B9C --- mov dword ptr [005174D8], 00000001

:00432B8D C705D874510001000000

:00432B97 E9E8000000 --- jmp 00432C84

手工更改方法:

文件偏移:32B86h

查找16进制代码:33 DB 66 3B C3 7D 0F C7

更改为:E9 F5 EA 09 00

回复消息窗口点击广告的程序段:

更改以前:

:0046221C FF15B8274D00 --- Call USER32.PtInRect ;判断是否在广告区域内点击

:00462222 85C0 --- test eax, eax

:00462224 0F84D8000000 --- je 00462302 ;不是就转

更改以后:

:0046221C FF15B8274D00 --- Call USER32.PtInRect ;判断是否在广告区域内点击

:00462222 85C0 --- test eax, eax

:00462224 E9D9000000 --- jmp 00462302 ;不管是不是都转

手工更改方法:

文件偏移:62224h

查找16进制代码:0F 84 D8 00 00 00 8B 46 56

更改为: E9 D9 00 00 00 00

弹出发送消息窗口之前的对象数据调用的程序段:

更改以前:

:0042513D 56 --- push esi

:0042513E 8BF1 --- mov esi, ecx

:00425140 FFB6F4000000 --- push dword ptr [esi+000000F4]

:00425146 FFB6B0000000 --- push dword ptr [esi+000000B0]

:0042514C E879810300 --- call 0045D2CA ;获得对象的数据结构首址

:00425151 33C9 --- xor ecx, ecx

:00425153 3BC1 --- cmp eax, ecx ;是否成功,非零就成功

:00425155 7431 --- je 00425188 ;失败转

:00425157 3988DC010000 --- cmp dword ptr [eax+000001DC], ecx

:0042515D 7508 --- jne 00425167

:0042515F 8988E8010000 --- mov dword ptr [eax+000001E8], ecx

:00425165 EB0A --- jmp 00425171

更改以后:

:0042513D 56 --- push esi

:0042513E 8BF1 --- mov esi, ecx

:00425140 FFB6F4000000 --- push dword ptr [esi+000000F4]

:00425146 FFB6B0000000 --- push dword ptr [esi+000000B0]

:0042514C E879810300 --- call 0045D2CA ;获得对象的数据结构首址

:00425151 33C9 --- xor ecx, ecx

:00425153 3BC1 --- cmp eax, ecx ;是否成功,非零就成功

:00425155 7431 --- je 00425188 ;失败转

:00425157 E9E4C40A00 --- jmp 004D1640 ;跳到我们的保存IP地址和端口的程序中

:0042515C 90 --- nop ;加一个空操作对齐

手工更改方法:

文件偏移:25157h

查找16进制代码:39 88 DC 01 00 00 75 08

更改为:E9 E4 C4 0A 00 90

保存IP地址和端口的附加程序:

添加代码:

:004D1640 8BDC --- mov ebx, esp ;保存原程序的栈指针

:004D1642 BC00194D00 --- mov esp, 004D1900 ;设置新的栈指针到无用的内存区域

:004D1647 50 --- push eax ;保存原程序几个有用寄存器

:004D1648 51 --- push ecx

:004D1649 52 --- push edx

:004D164A 56 --- push esi

:004D164B FFB018020000 --- push dword ptr [eax+00000218] ;对象端口的地址

:004D1651 FFB014020000 --- push dword ptr [eax+00000214] ;IP地址的字符串指针

:004D1657 6820174D00 --- push 004D1720 ;指向“%s:%d”,这是printf的模式字符

:004D165C 6800174D00 --- push 004D1700 ;输出到的地方

:004D1661 8B3532CE4900 --- mov esi, dword ptr [0049CE32] ;其他地方调用wsprintfA的地址

:004D1667 FF16 --- call dword ptr [esi] ;esi为已经重定位好了的wsprintfA的地址

:004D1669 83C410 --- add esp, 00000010 ;恢复栈指针

:004D166C 5E --- pop esi ;恢复有用的寄存器值

:004D166D 5A --- pop edx

:004D166E 59 --- pop ecx

:004D166F 58 --- pop eax

:004D1670 3988DC010000 --- cmp dword ptr [eax+000001DC], ecx ;原程序00425157处被改掉的有用代码

:004D1676 8BE3 --- mov esp, ebx ;恢复为以前的栈指针

:004D1678 E9E03AF5FF --- jmp 0042515D ;跳转到原程序

:004D167D 90 --- nop

:004D167E 90 --- nop

:004D167F 90 --- nop

手工更改方法:

文件偏移:D1640h

添加16进制代码:

8B DC BC 00 19 4D 00 50 51 52 56 FF B0 18 02 00

00 FF B0 14 02 00 00 68 00 8B 35 32 CE 49 00 FF

39 88 DC 01 00 00 8B E3 20 17 4D 00 68 00 17 4D

16 83 C4 10 5E 5A 59 58 E9 E0 3A F5 FF 90 90 90

显示IP地址和端口的附加程序:

添加代码:

:004D1680 803D00174D003A --- cmp byte ptr [004D1700], 3A ;判断字符内存区第一个字符是不是冒号,

是就说明没有IP地址

:004D1687 7509 --- jne 004D1692 ;不是转到显示程序

:004D1689 66C70500174D003000 --- mov word ptr [004D1700], 0030 ;在字符内存区写上一个“0”

:004D1692 6800174D00 --- push 004D1700 ;字符内存区首址

:004D1697 FFB660010000 --- push dword ptr [esi+00000160] ;广告窗口的窗口句柄

:004D169D A1E8714A00 --- mov eax, dword ptr [004A71E8] ;其他地方调用SetWindowTextA的地址

:004D16A2 FF10 --- call dword ptr [eax] ;eax为已经重定位好了的SetWindowTextA的地址

:004D16A4 E9D415F6FF --- jmp 00432C7D ;跳到广告点击程序之后

:004D16A9 90 --- nop ;无用的空操作,只是为了对齐好看

:004D16AA 90 --- nop

:004D16AB 90 --- nop

:004D16AC 90 --- nop

:004D16AD 90 --- nop

:004D16AE 90 --- nop

:004D16AF 90 --- nop

wsprintf所用到的模式字符串:

:004D1720 25733A2564 --- "%s:%d"

手工更改方法:

文件偏移:D1680h

添加16进制代码:

80 3D 00 17 4D 00 3A 75 09 66 C7 05 00 17 4D 00

30 00 68 00 17 4D 00 FF 4A 00 FF 10 E9 D4 15 F6

B6 60 01 00 00 A1 E8 71 FF 90 90 90 90 90 90 90

文件偏移为:D1720h

添加16进制代码:25 73 3A 25 64

消息发送对话框中广告窗口样式的更改:

更改样式字:

更改以前的窗口样式(style)是50000012h WS_CHILDWINDOW|WS_VISIBLE|SS_LEFT|SS_ETCHEDFRAME

更改以后的窗口样式(style)是50000201h WS_CHILDWINDOW|WS_VISIBLE|SS_LEFT|SS_CENTER|SS_CENTERIMAGE

手工更改方法:

文件偏移:141EFCh

查找16进制代码:12 00 00 50

改为:02 01 00 50

代码段段属性修改:

更改属性字:

更改以前的代码段属性为60000020h CER(包含代码,可执行,可读)

更改以后的代码段属性为C0000020h CRW(包含代码,可执行,可读写)

手工更改方法:

文件偏移:21Ch

查找16进制代码:20 00 00 60

改为:20 00 00 C0

(后记:真是佩服邹丹大哥,尽管这只是针对很早之前的QQ,但是,对于新版的QQ,原理还是一样的,邹丹大

哥现在不在开发这个QQ补丁了,看来只好我们自己努力了!)

 

3)--- 转载自水木清华BBS

发信人: shge(沧海月明时)

信区: Hacker

标 题: 公开OICQ所有通讯协议!

发信站: BBS 水木清华站 (Fri Aug 17 10:06:51 2001)

OICQ服务器系统通讯协议

协议说明:协议由报文头(T)+发送者(T)+接收者(T)+报文类型(T)+报文长度(L)+报文内容组成

发送者和接收者是系统内的程序种类,QQ服务器0x01,传真服务器0x02,WEB服务器0x03,打印服务器是

0x04,聊天服务器是0x05,QQ用户是0x0A。

QQ用户到OICQ服务器的通讯协议

引导符(0x81+0x0A+0x01)

报文类型 报文内容 报文说明

0x01 昵称(S)+肖像(M)+用户密码(S)+性别(T)+年龄(T)+真实姓名(S)+国家 /地区(T)+省(T)

+市(S)+地址(S)+邮编(S)+学历(T)+毕业院校(S)+职业( T)+电话(S)+寻呼(S)+电邮(S)+爱

好(S)+说明(S)+身份验证(T)新用户注册,身份验证用于当有人要将他加入好友时询问是否允许

0x02 服务号(L)+密码(S)+注册方式(T)老用户注册,方式分为0正常,1隐身

0x03 服务号(L)+对方服务号(L)+内容(S)发送信息到某人

0x04 服务号(L)+组号(L)+内容(S)广播信息,组号=0为全体

0x05 服务号(L)+朋友服务号(L)查看朋友资料

0x06 服务号(L)+组名称(S)增加组

0x07 服务号(L)+组编号(T)+组名称(S)修改组名称

0x08 服务号(L)+组编号(T)删除组

0x09 服务号(L)+移动人数(T)+{朋友服务号(L)+目的组号(T)}移动组成员

0x0a 服务号(L)+起始编号(L)+回传个数(T)+查找标志(T)看谁在线上 查找标志 1=向小找 2=向大找

0x0b 服务号(L)+SQL语句(S) 自定义查找 0x0c 服务号(L)+朋友服务号(L)增加好友

0x0d 服务号(L)+朋友服务号(L)+加入原因(S)请求加入好友

0x0e 服务号(L)+朋友服务号(L)删除好友

0x10 服务号(L)+显示模式(T)更改显示方式 1上线 2隐藏 3免打扰 4离线

0x11 服务号(L)+监视服务号(L)监视某人谈话

0x12 服务号(L)+昵称(S)+肖像(M)+用户密码(S)+性别(T)+年龄(T)+真实姓名(S)+国家/地区(

T)+省(T)+市(S)+地址(S)+邮编(S)+学历(T)+毕业院校(S)+职业(T)+电话(S)+寻呼(S)+电

邮(S)+爱好(S)+说明(S)+身份验证(T)更改用户基本信息

0x13 服务号(L)+朋友服务号(L)+文件名(S)+文件长度(L)请求发送文件

0x14 服务号(L)+朋友服务号(L)+允许/拒绝 是否允许发送文件

0x15 服务号(L)+朋友服务号(L)+文件内容(B)发送文件

0x16 服务号(L)连接测试报文

0x17 服务号(L)+朋友服务号(L)+同意标志(T)应答对方请求加入好友 0=拒绝 1=同意

QQ服务器到QQ的通讯协议

报文类型 报文内容 报文说明

0x01 成功/失败(T)+服务号(L)新用户注册结果返回

0x02 成功/失败(T)+组个数(T)+{组名称(S)+组编号(T)+朋友个数(T)+{朋友 服务号(L)+肖像编

号(T)+朋友状态(T)+朋友昵称(S)}}老用户注册结果返回 朋友状态 1=上线 2=隐藏 3=免打扰 4=离线

0x03 标志(T)+ 朋友服务号(L)+信息(S)+信息类型(T)标志 1=系统 2=用户, 发送消息 服务号0=系统

消息 1=用户某某已经把你加为好友 2=用户某某请求你通过身份验证 3=用户某某同意了你的验证要求 4=用户

某某拒绝了你的验证请求

0x04 成功/失败(T)+朋友服务号(L)+昵称(S)+肖像(M)+性别(T)+年龄(T)+真实姓名(S)+国家

/地区(T)+省(T)+市(S)+地址(S)+邮编(S)+学历(T)+毕业 院校(S)+职业(T)+电话(S)+寻呼

(S)+电邮(S)+爱好(S)+说明(S)朋友信息回送

0x05 成功/失败(T)+组编号(T)+组名称(S)增加组结果回送1/0

0x06 成功/失败(T)+组编号(T)+组名称(S)修改组名称结果回送1/0

0x07 成功/失败(T)+组编号(T)删除组结果回送1/0

0x08 成功/失败(T)移动组成员结果回送1/0

0x09 成功/失败(T)+在线个数(T)+{服务号(L)+昵称(S)+肖像(M)+省(T)+市 (S)}查找在线人员

结果回送

0x0a 成功/失败(T)+找到个数(T)+{服务号(L)+昵称(S)+肖像(M)+省(T)+市 (S)}自定义查找结果回送(最多50)

0x0b 标志(T)+朋友服务号(L)增加好友结果回送,标志 0=失败 1=成功 2=需要身份验证 3=对方不允许加

入 4=需要身份验证且不在线

0x0c 朋友服务号(L)+昵称(S)+肖像号(M)+朋友状态(T)给在线用户增加好友

0x0e 成功/失败(T)+朋友服务号(L)删除好友结果回送

0x10 服务号(L)+显示模式(T) 显示模式回送 1=上线 2=隐藏 3=免打扰 4=离线

0x11 成功/失败 更改用户基本信息结果回送

0x12 朋友服务号(L)+文件名(S)+文件长度(L)请求发送文件

0x13 朋友服务号(L)+允许/拒绝 是否允许发送文件 1允许 0拒绝

0x14 朋友服务号(L)+文件内容(B) 发送文件 0x15 朋友服务号(L)+当前状态(T)朋友状态回送(系统

发送)1=上线 2=隐藏 3=免打扰 4=离线

0x16 服务号(L)连接测试