`
luotuoass
  • 浏览: 639423 次
文章分类
社区版块
存档分类
最新评论

恶搞英语大厅的原理(准确来说应该是恶搞IE)

 
阅读更多

恶搞英语大厅的原理(准确来说应该是恶搞IE)

源代码下载地址: http://download.csdn.net/detail/linger2012liu/4033059

由于个人知识有限,若发现不对,敬请指正。

恶搞程序的本意应该不是针对我们学校的英语大厅,而是IE。恰好英语大厅是用的是IE内核,于是我们也可以用它来恶搞大厅了。

恶搞是这样子的:修改某网页的源代码(当然是在我们客户端),然后更新显示。正如作者所描述的:“此程序除了恶搞外,其实就是一个IE内容修改的程序!还有什么用途~~

发挥你的想象力吧!“

那么我们恶搞大厅时各个步骤做了什么呢?下面分析一下。首先,点击左上角的“放大镜”并拖到英语大厅,该步骤是获取大厅的窗口句柄,并根据句柄获得该窗口的html代码。然后我们把一段html代码(可能夹杂着javascript代码)插入到代码中的适当位置。这时,大厅会出现一个按钮,点击按钮后,会出发相应的javascript的运行。插入的代码不同,效果也不同,比如可能是显示正确答案,可能是把正确答案都填上去了。

由于现在上不了大厅了,所以我直接拿网页做测试,当然原理都是一样的。首先写以下html代码,另存为test.html。

<html>

<body>

<p>请点击这里</p>

<!-- <ponmousedown='alert("hehe")'>请点击这里</p> -->

</body>

</html>

打开改网页,将放大镜放到网页上,抓取html代码,恶搞显示如下:


修改以下代码,点击开始恶搞,如下(主要是把注释的代码复制到前面,把点击事件添加到文本中)

这时,剧本应该是这样演的,点击文本后会弹出提示框。但也许是我IE设置问题,出现如下,


然后就点击那里允许执行阻止的内容,其实就是js代码。再点击一下开始恶搞(因为刚才的操作可能自动重新加载页面了)。到网页中,点击文字,出现提示框了。设想成功,恶搞就是修改IE代码的功能。

那么接下来是怎么写一个修改一个IE的网页源代码的程序。查阅了相关的知识,实现主要是这样:打开网页,找到要修改网页的窗口句柄,根据句柄改掉对应网页的内容。这种方法,因为是用窗口句柄做中介的,因此肯定也适合英语大厅等一类用IE内核的程序。

首先新建一个c#的控制台程序,我这里命名为fuckIE,在引用中添加Microsoft.mshtml这个引用。

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Windows.Forms;

usingSystem.Runtime.InteropServices;

using mshtml;

namespace fuckIE

{

class Program

{

//一些api函数的声明

[DllImport("USER32.DLL")]

public static extern IntPtr FindWindow(stringlpClassName, string lpWindowName);

[DllImport("user32.dll")]

privatestatic extern IntPtr FindWindowEx(IntPtrhwndParent, IntPtr hwndChildAfter, string lpszClass, stringlpszWindow);

[DllImport("user32.dll", EntryPoint = "EnumChildWindows")]

public static extern bool EnumChildWindows(IntPtrhwndParent, EnumChildProc EnumFunc, IntPtr lParam);

[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]

public static extern uint RegisterWindowMessage(stringlpString);

[DllImport("oleacc.dll", PreserveSig = false)]

[return:MarshalAs(UnmanagedType.Interface)]

public static extern object ObjectFromLresult(UIntPtrlResult, [MarshalAs(UnmanagedType.LPStruct)]Guid refiid, IntPtrwParam);

[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]

public static extern IntPtr SendMessageTimeout(IntPtrhWnd, uint Msg, UIntPtrwParam, IntPtr lParam, SendMessageTimeoutFlags fuFlags, uint uTimeout, out UIntPtr lpdwResult);

public enum SendMessageTimeoutFlags:

uint

{

SMTO_NORMAL = 0x0000,

SMTO_BLOCK = 0x0001,

SMTO_ABORTIFHUNG = 0x0002,

SMTO_NOTIMEOUTIFNOTHUNG = 0x0008

}

public IntPtr destHandle = IntPtr.Zero;

public delegate bool EnumChildProc(IntPtrhwnd, IntPtr lParam);

boolFindChildClassHwnd(IntPtr hwndParent, IntPtr lParam)

{//该函数用来从一个顶级窗口(我这里是IE的打开的某网页)查找类名为Internet Explorer_Server的子窗口

IntPtrhwnd = FindWindowEx(hwndParent, IntPtr.Zero,"Internet Explorer_Server", null);

if(hwnd != IntPtr.Zero)

{

//pfw->m_hWnd= hwnd; // found: save it

destHandle = hwnd;

returnfalse; // stop enumerating

}

EnumChildWindows(hwndParent,FindChildClassHwnd, lParam); // recurse

//每段枚举子窗口,递归调用

returntrue;

}

// keep looking

[STAThreadAttribute]

static void Main(string[]args)

{

// IntPtr ieh = FindWindow("InternetExplorer_Server",null); //这样会失败,因为这只能适合顶级窗口

IntPtrieh = FindWindow(null, "E:\\past\\恶搞\\fuckIE\\fuckIE\\test.html- linger");

//首先找到顶级窗口,第二个参数为窗口标题,即如下图片的左上角的文字


Console.WriteLine("ie句?柄À¨²:êo"+ieh);

////E:\past\恶?搞?\fuckIE\fuckIE\test.html - linger

if(ieh == IntPtr.Zero)

{

Console.WriteLine("can not find the window");

return;

}

Programinstance = new Program();

instance.FindChildClassHwnd(ieh, IntPtr.Zero);

//查找类名为InternetExplorer_Server的子窗口

if(instance.destHandle == IntPtr.Zero)

{

Console.WriteLine("can not find the window");

return;

}

Console.WriteLine("目?标À¨º句?柄À¨²"+instance.destHandle);

//目标句柄找对了,注意用spy++找的 是16进制

UIntPtrlRes = new UIntPtr();

uintapp2_GenerateEvent = RegisterWindowMessage("WM_HTML_GETOBJECT");

SendMessageTimeout(instance.destHandle, app2_GenerateEvent, UIntPtr.Zero, IntPtr.Zero,SendMessageTimeoutFlags.SMTO_NOTIMEOUTIFNOTHUNG,1000, out lRes);

//IHTMLDocument得Ì?不?到Ì?body.innerHTML

IHTMLDocument2obj = (IHTMLDocument2)ObjectFromLresult(lRes,typeof(IHTMLDocument).GUID,IntPtr.Zero);

Console.WriteLine(obj.body.innerHTML);

//obj.body.innerHTML= "<p onmouseover='alert(\"hehe\")'>本À?来¤¡ä什º2么¡ä都?没?有®D的Ì?</p>";

obj.body.innerHTML = " <ponmousedown='alert(\"hehe\")'>请点击这里</p>";

//修改为自己想要的代码

Console.WriteLine(obj.body.innerHTML);

}

}

}

下面测试效果。

打开test.html网页,此时不要点击其他网页, 也不要最小化IE浏览器,不然是找不到该句柄的。(人家恶搞的程序是用拖拽放大镜的方法找的,我对界面编程不是很了解,所以只好用窗口标题找窗口句柄。)


运行程序,


还是出现这个,


点击那里,再点击“允许阻止的内容”,出现下面对话框,再点确定。


关闭刚才打开的控制台程序,再次运行。

到网页中点击那里的文字,实验成功!!!

有个疑问就会如果查看该网页源代码,发现源代码并没有改掉,对浏览器的机理还不是很了解啊。不过猜测,IE这个查看源文件的功能,可能是从服务器那里拿来的,当然我这里是本地文件,服务器就是自己电脑。

一个恶搞程序大概如此。如果把上面的c#代码稍微修改一下, 就可以用到英语大厅了。主要是窗口标题名,和怎么修改html代码。前者比较容易,用任务管理器就可以准确看到进程的窗口标题名,英语大厅也不例外,当然我电脑没有大厅。


至于修改html代码就是做一些字符串处理,还要懂一些javascript。当然,修改html之前,得研究一下源代码,看一下怎么可以用javascript把答案显示出来,或者把答案填上去。

看了之前的两份插入代码,都是在原有html里添加一个button,然后触发一个javascript事件,一是显示正确答案,二是把正确答案填上去。

还有,我们可以恶搞英语大厅的一个前提,是答案已存在我们客户端电脑里,也许做大厅软件的队伍为了方便还是为了减轻服务端的压力,把答案检测放在客户端进行,服务端负责接收分数就可以了。所以,我觉得恶搞大厅有3种渠道,一是分数的来源,二是分数的缓存,三是数据包。第一,我们IE恶搞的方法就是属于对分数的来源做处理,把正确答案填上去,分数自然高。第二,我想在客户端里一定有几个变量用来存储分数,只要修改了他们即可,也许在javascript就有。第三,分数检测出后,肯定会给服务端发送包含分数的数据包,只要伪造一个数据包,发送过去,你想拿多少分都可以。

更正:后来苏淦告诉我上面所说的3种方法后两种还是不行的,因为大厅记录了我们的答案,应该是把我们填的答案也提交上去了吧,不可能傻逼到存在本地磁盘

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics