<?xml version="1.0" encoding="UTF-8"?><!-- generator="WordPress/2.7.1" -->
<rss version="0.92">
<channel>
	<title>mengxp杂谈</title>
	<link>http://www.deadc0de.com</link>
	<description>a piece world of win32asm</description>
	<lastBuildDate>Tue, 17 Nov 2009 04:29:54 +0000</lastBuildDate>
	<docs>http://backend.userland.com/rss092</docs>
	<language>en</language>
	
	<item>
		<title>war3 1.20e dota反互通图作弊 及 war3对战平台原理</title>
		<description>大部分互通图在作弊的时候都需要输入作弊指令 -xxx
而且为了掩人耳目有些指令具有迷惑作用比如 -ma空格空格空格
但是如果设置聊天对象为ob那么队友也看不到你输入的指令

但事实上这一切尽在服务器眼中
玩家输入的任何游戏指令(-打头)
都会通过26号游戏协议包(F7 26 xx xx)发送到服务器

假如我们做了一个服务器插件
监控玩家使用的游戏指令
就可以达到一定的监测作弊效果

然后配合踢人功能惩罚作弊者...那么...

 

另外在分析魔兽协议的时候又学习了一下iocp模型
war3为每个连接创建了一个线程接收网络数据包
使用WSARecv接收数据
如果返回-1并且WSAGetLastError = ERROR_IO_PENDING
那么就使用GetQueuedCompletionStatus等待IO完成
另外通过lpCompletionKey结构，可以得知被等待的socket句柄和缓冲区

 

至此我们也可以猜测各种游戏平台的工作原理
hook socket把TCP改成UDP
hook connect返回成功
hook AcceptEx或其他。。
hook send通过sendto把数据传到服务器由服务器转发，要确保数据正确到达
hook WSARecv，貌似可以阻塞也可以不阻塞，总之数据来了就返回，如果不阻塞。那么再
hook GetQueuedCompletionStatus，等待数据到来
大体应该就是这样子，全是猜测，下一步可以构想一下自己实现的对战平台的网络模型

另外我想数据可以是由服务器中转的，也可以是用UDP穿墙技术实现的。
区别就是经过服务器中转。还可以多实现一些功能
比如聊天监控，作弊监控…… </description>
		<link>http://www.deadc0de.com/archives/war3_1_20e_anti_cheat.html</link>
			</item>
	<item>
		<title>ping monitor 监测ping的小工具</title>
		<description>点此下载(3.6KB)

PingMonitor是一个专门监测网络线路ping值的小工具

你完全可以在命令行中使用 ping ip -t 代替它

但这个小工具使用起来将更加便捷直观。

这个工具可以同时监控2个ip

在Options.ini里.你可以设置电信、网通、铁通或局域网等任何IP地址

还可以个性化设定界面的颜色。

 

如果你的线路是ADSL，而且是你是个在线游戏爱好者。

我相信这个工具将会对你很有用。

 </description>
		<link>http://www.deadc0de.com/archives/ping-monitor.html</link>
			</item>
	<item>
		<title>单步跟踪引擎.太慢</title>
		<description>原本想做个注入dll式的单步跟踪软件，记录某个线程的执行记录
现在看来这想法太离谱了，现在引擎做出来了，发现跟踪30000行指令需要10秒，加上记录也是10秒左右
想想我准备调试的那些可怕的程序，运行起来的话。。这。。。太扯了 :&#60;

还是改做调试器吧 :&#62;

 

00401343: push 00402169h
00401348: push 00402162h
0040134D: call 004012C5h
004012C5: push ebp
004012C6: mov ebp , esp
004012C8: add esp , F4h
004012CB: lea eax , dword ptr [ebp-04h]
004012CE: push eax
004012CF: push 04h
004012D1: push 00h
004012D3: push dword ptr [ebp+08h]
004012D6: push 80000002h
004012DB: call RegOpenKeyExA (advapi32.dll)
004013B4: jmp RegOpenKeyExA (advapi32.dll)
........: Out of watch limit, wait for ret ...</description>
		<link>http://www.deadc0de.com/archives/step-trace-bullsh1t.html</link>
			</item>
	<item>
		<title>Dr.Com客户端的替代 - Free Dr.COM win32/linux</title>
		<description>点此下载...

 

Dr.COM是北京城市热点开发的一款基于局域网的宽带接入服务器，广泛应用于高校校园网、小区宽带。

邮电学院南校区使用的就是Dr.COM服务器做宽带接入，使用了专用的客户端进行直通方式认证。

该客户端的功能很强大，但我们学校使用的客户端比较简单。主要做了如下2条限制。

 

绑定ARP缓冲中所有IP为非法MAC，阻塞局域网内TCPIP通讯，防止做共享网络。同时也无法玩局域网游戏(TCP/IP)

检测常见的共享网络的软件，并加以提示，停止激活Dr.COM网关。拒绝服务。

 

我们只需模拟Dr.COM客户端激活Dr.COM网关的方法。即可抛弃官方客户端及如上限制。

 

使用方法

拨号宽带连接，运行本软件。提示已经激活即可上网。

最小化后隐藏窗口，再次运行本软件可以调出窗口。

本软件没有设置自动运行，可以在程序-&#62;启动中创建快捷方式。

 

常见问题

1.如果提示无法绑定 UDP 61440 端口，请检查是否已经卸载原来的客户端。(官方客户端为ishare_user.exe进程)

2.如果提示接收数据2超时，请检查程序的连接是否被 Windows阻止。必要时可以关闭 Windows 的防火墙。

   XP环境下服务名为 Windows Firewall/Internet Connection Sharing (ICS)
   Vista/Win7环境下服务名为 Windows Firewall

  禁用这个服务即可。 </description>
		<link>http://www.deadc0de.com/archives/free-drcom.html</link>
			</item>
	<item>
		<title>NBP开发手记</title>
		<description>以前对PXE只有一点点了解，最近在研究PXE无盘启动XP，所以学习了PXE的spec文档，对PXE有了初步的认识，同时又在调试时遇到了很多的很挫的问题。现在把它们记录下来。

所谓NBP是来自PXE文档的说法，全称 Network Bootstrap Program，也就是我以前理解的 PXE Boot File。他的作用就是 Hook Int 13h 虚拟一个硬盘，对硬盘的读写，通过 PXE API(通常使用UDP)定向到网络，返回数据给调用者，达到通过网络启动的目的。

 

一、NBP工作流程

1.Int 1Ah 获取PXE接口，这没什么说的。分2.0和2.1或以上版本2种区别，一般只需要兼容2.1就行。
2.PXENV_GET_CACHED_INFO 的3号功能，获取自己的IP和服务器IP。
3.PXENV_UDP_OPEN 初始化 UDP 网络接口。
4.Hook Int13h,I/O PXENV_UDP_READ/PXENV_UDP_WRITE
5.读 MBR 到 0000:7C00。
6.跳转 0000:7C00。

这些流程除了第四步Hook Int13h都不难，只是UDP部分需要注意处理丢包的问题。C/S用会话ID，很好解决。
另外那个UDP接口，收到大于4K的包，容易卡死在UDP_RECV里很久才返回一个错误。所以一次收发包最好小于4KB……
二、Hook Int13h

对于无盘启动XP，需要处理如下的功能号。并尽量按照标准来处理。。

FUN00: IO复位
FUN02: 读扇区
FUN03: 写扇区
FUN08: 读磁盘参数
FUN15: 读磁盘类型
FUN41: 检验扩展功能是否存在
FUN42: 扩展读
FUN43: 扩展写
FUN48: 扩展读磁盘参数

貌似对于无盘启动XP，处理写操作好像并不是必要的。一般情况XP在内核启动前不需要写操作。内核启动后加载磁盘驱动，然后才会有写操作，那时候已经不需要Int13h了。不过NTLDR是设计了写操作接口的，说不准，没准啥时候来个FUN03/43，所以最好还是处理了吧。

而且我在做NBP之前还在想，如果进入保护模式后，还使用Int13h怎么办？因为PXE文档中对保护模式中使用PXE API的说明很模糊。SDK中也没有例子，做起来会很烦，可是真正做的时候发现，在进入保护模式后，根本不需要Int13h了，系统会使用磁盘驱动来完成IO。

而且我发现XP在启动的时候并没有使用扩展Int13h功能，不过调试发现Win7的 Boot Sector/Mgr 会使用Int13x。

 
三、万恶的 CHS 寻址

（以下段落引用互联网。。。有更正）
----- Quote Start-----
到目前为止，人们常说的硬盘参数还是古老的 CHS (Cylinder/Head/Sector)参数。那么为什么要使用这些参数，它们的意义是什么？它们的取值范围是什么？
很久以前(long long ago ...)，硬盘的容量还非常小的时候，人们采用与软盘类似的结构生产硬盘。也就是硬盘盘片的每一条磁道都具有相同的扇区数。由此产生了所谓的3D参数 (Disk ...</description>
		<link>http://www.deadc0de.com/archives/nbpdevelopment.html</link>
			</item>
	<item>
		<title>暑假搞scsi虚拟盘</title>
		<description>通过分析学习miniram和minifile的代码，实现了不需要定时器(TimerCall)的scsi驱动程序，效率很高，但当块大小为2K甚至更低的时候。效率依然赶不上DaemonTools。DT的scsi驱动很小，主要的处理都在他的总线驱动里，没有使用ZwReadFile或者ZwWriteFile而直接向文件系统?发送irp读数据。抛开缓存机制不说，也就是说我用纯内存当虚拟盘，1K块大小读取速度只有11MB/s，而DT可以达到50MB/s以上，真是变态啊，都是发irp，差距咋就那么大呢。可恶的ms scsiport啊。。

结合tdi又做出了网络虚拟盘。但无法应用于无盘网络系统，tdi在系统启动时无法使用，只能使用ndis，这样我还需要自己实现一个tcp协议…… </description>
		<link>http://www.deadc0de.com/archives/vscsidisk.html</link>
			</item>
	<item>
		<title>也谈向Richedit插入动态Gif的实现</title>
		<description>最近在做IM软件，需要实现向Richedit插入表情，表情是动态的GIF图像。

由于以前没有做过关于richedit的开发，百度了下，需要使用OLE技术。也就是说，插入的图片都是一个OLE对象。而RICHEDIT则是一个OLE容器，相关链接如下。

How to insert a bitmap into an RTF document using the RichEdit control in Visual C++ 6.0
http://support.microsoft.com/default.aspx?scid=kb;en-us;220844

Animated Emoticons like those in MSN Messenger(英文版)
http://www.codeproject.com/KB/edit/AnimatedEmoticon.aspx

Animated Emoticons like those in MSN Messenger(中文版)
http://blog.csdn.net/dTianx/archive/2004/11/17/184949.aspx

DynamicGif作者blog
http://blog.csdn.net/kql01

 

第一个链接是微软提供的部分代码，只能用于插入BMP图片。使用了OleCreateFromFile创建的ole对象。

第二个、第三个链接都是dTianx写的，使用QQ的ImageOle.dll创建了ole对象。提供全部源代码。

第四个链接是一牛自己做的一个控件，导出函数InsertGifToRichedit2A可以方便地插入任意GIF。只提供DLL文件，而且只有1.21版本的，据说作者开发了1.4版本但他没有开放下载。
我对这4个方法逐一试验，结果发现这些方案都不可靠。下面我将详细的介绍，我假设各位读者从前没接触过RICHEDIT嵌入OLE这方面内容，2个星期前我也一无所知……

首先第一个不用说，只能插入BMP图片，不符合我们的要求，但这段代码已经可以让我们了解了插入一个OLE对象的全部步骤。

第三个DynamicGif使用导出函数InsertGifToRichedit2A，方便地插入了任意Gif图片，但是我发现他放出的这个1.21版本有问题，这个问题发生在拖动滚动条的时候，richedit会很不正常……

放弃使用了DynamicGif后我把所有的赌注加在了ImageOle上，可是可是待我把一切实现在汇编上的时候。我发现噩梦到来了……(-__-！夸张一小下)。

首先。上面的例子创建GifAnimator实例，获取IGifAnimator接口，IGifAnimator::LoadFromFile载入图片，然后调用神奇的IGifAnimator::TriggerFrameChange函数，调用IRichEditOle::InsertObject插入ole对象。顺理成章，但是这个例子有一个很明显的bug就是在显示透明gif的时候没有擦除背景。如下图所示。

 

另外当我实现在汇编上的时候我发现刷新有闪动问题，可能是InvalidateRect的第三个参数bErase被设置了TRUE，可是我调试发现ImageOle在调用这个api的时候bErase为False。郁闷地研究了好几天，终于发现这一切的一切居然是一个扩展风格导致的，WS_EX_TRANSPARENT，透明风格，而dTianx和qq的richedit的确有这个扩展风格。-_-!!! 当我给richedit加入这个风格后，刷新的确不闪了，但richedit背景与窗体相同，这就需要子类化richedit响应WM_ERASEBKGND消息，手工画背景为白色。

解决了这个后又开始着手解决显示透明gif的问题。这个问题应该源于GDI+的GdipImageDrawRectI函数，它只绘制了不透明的部分到DC上，我不知道qq是怎么解决的，我觉得应该有一个函数可以关掉GID+的这个特性:只绘制不透明部分到DC。但对GDI+非常不了解，找了好久没有找到。我想出来的解决方法是hook这段代码，加入一个创建白色刷子刷白色背景，然后再调用GdipImageDrawRectI绘制gif帧。这样每次绘制GIF帧背景都会被刷成白色。而且的确实现了~

在实验过程中，我还发现如果使用类名称为RICHEDIT20A版本的richedit会导致内存泄露问题，就是删除了已经插入的图片对象内存依然不释放，使用类名称为RICHEDIT版本的richedit没有此问题。而qq使用的是RICHEDIT20A，我复制了qq目录的riched20.dll仍然存在这个问题，我不知道qq有没有这个问题，以及他是怎么怎么解决的。

然后当我把代码转移到我的IM工程上我发现了更严重的问题。嵌入过多的ole会导致程序崩溃，崩溃点是riched20.dll，查看调用堆栈发现是其内部造成的，我无法查明原因。这个错误so奇怪，在实验工程上无论插入多少个图片都不会崩溃，一转移到IM工程上就有问题，我屏蔽了很多很多代码，最终发觉可能跟线程有关。在WM_INITDIALOG中插入多少个都没问题，在另外的线程插入就有问题，我想，把插入ole的代码放在窗口过程里。用SendMessage触发来添加，结果还是不行，很奇怪很奇怪。。。

还有另外一个很令我崩溃的问题，第一次创建richedit，插入gif图片可以，但当你销毁这个带有richedit的窗口，然后再创建，再次插入gif图片，图片不会动了（打开聊天窗口，插入gif，正常；关闭聊天窗口，打开聊天窗口，插入gif，gif不会动）。又另我百思不得其解。为此我调试了ImageOle，晓得了ImageOle的原理。

ImageOle读取了一个图片后，依赖接口IViewObject::OnDraw实现刷新ole区域显示gif的不同帧。而这个OnDraw是需要InvalidateRect触发的。这就需要一个定时器来定时调用InvalidateRect实现刷新，这个定时器是由ImageOle内部创建的，是在CreateInstance的时候。而且他有个判断，如果已经创建过（句柄不为0），就不需要再创建了。当我销毁我的聊天窗口的时候，这个定时器居然神奇般地不见了……所以再次插入gif就不能自主动态刷新gif了。dTianx的mfc工程，他并未销毁窗口，用spy++可以看到当关闭窗口的时候，窗口只是变为了invisable……所以没有这个bug。

这种种的问题逼迫我去寻找其他的替代DLL。

我发现浩方平台也有个ImageOle，接口名换了，但也有LoadFromFile,TriggerFrameChange，和QQ的ImageOle惊人的相似，好神奇~两者难道有某种关联？ImageOle的开发者究竟是谁呢？不管这些，我实验调用浩方的ImageOle.dll也不成。然后又寻找了飞信、百度Hi……

找到了很多。都用不明白。

这迫使我选择另一条崎岖的路。

另一条最有可能成功的路。。

自己造个ActiveX实现OLE对象嵌入。。

需要编程实现n个COM接口
IDispatch
IOleObject
IOleInPlaceObject
IOleInPlaceActiveObject
IOleControl
IDataObject
IProvideClassInfo
IPersistStorage
IPersistStreamInit
IPersistPropertyBag
IViewObject2
ISpecifyPropertyPages
ICategorizeProperties
IConnectionPointContainer
IRunnableObject

接口太多了，工程量巨大，我肯定自己搞不定的，不过好在印象里masm32包里有个asmctrl的工程，是一个activex控件，可以被vb调用，肯定已经实现了这些东西，找来masm32 v9果然有。尝试把他插入richedit里，发现插入1个以上ole的绘制就有问题。看readme可以知道这个工程的作者。

他就是japheth，一个德国的汇编超人……

作品有牛x闪闪的COMView和牛x闪闪闪的masm兼容编译器JWasm。otz

他对COM的研究可谓是非常的透彻了，不然怎么可能敢用汇编写ActiveX~~

超人的网站 http://www.japheth.de

网站的 COM &#38; Assembly 栏目里有一个ASMCtrl工程。版本是2.5.5，v9里的可能是1.0版本，看历史记录可知后续版本修正了bugs。而且2.0版本后使用了大量的宏，因为这些宏，我读他的代码变得非常非常难。。看了超人japheth的代码我才知道汇编原来是这么这么玩的，太牛x的……太令人无语了。看不懂，给超人写信要来了1.3的版本，1.3代码比2.x好理解，只用了少量的宏，不过编译后插入richedit依然存在bug。无奈只有使用2.5.5版本当模板做我的PicOlePlus了。

然后结合我对调试ImageOle得出的经验和对GDIPlus的学习。很费力地修改了ASMCtrl工程，得到了伟大的PicOlePlus.dll这个东东

下面是我做的一些主要更改。

1.CAsmClass.inc里面添加一些类私有变量，还需要在CAsmClass的MEMBER里申明

  hGdiplus dd ?
  pImage dd ?
  dwWidth dd ?
  dwHeight dd ?
  dwFrameCount dd ?
  pPropertyItem dd ? ;id len type ...</description>
		<link>http://www.deadc0de.com/archives/insert-gif-to-richedit.html</link>
			</item>
	<item>
		<title>探究 LoadImage 内部的图像缩放函数</title>
		<description>最近研究界面编程涉及到了位图缩放。但发现系统提供的 StretchDIBits 缩放效果很不理想。但又研究发现 LoadImage 这个 API 内部实现了缩放功能。下面是 LoadImage 原型。

HANDLE LoadImage(
    HINSTANCE hinst,  // handle of the instance that contains the image
    LPCTSTR lpszName, // name or identifier of image
    UINT uType, // type of image
    int cxDesired, // desired width
    int cyDesired, // desired height
    UINT fuLoad // load flags
   );
设置此函数的 cxDesired cyDesired 参数实现缩放，效果较好。但是这个函数只能从文件或资源中获取位图。不方便用于已读入内存的位图。

而 StretchDIBits ...</description>
		<link>http://www.deadc0de.com/archives/stretch-func-in-loadimage.html</link>
			</item>
	<item>
		<title>Hello world！</title>
		<description>从今天开始我也加入blog阵营啦

使用WordPress程序

欢迎大家常来玩

嘿嘿~ </description>
		<link>http://www.deadc0de.com/archives/hello-world.html</link>
			</item>
</channel>
</rss>
