首页
社区
课程
招聘
[旧帖] 请教一些关于外挂的基础知识 0.00雪花
发表于: 2015-10-21 21:28 5032

[旧帖] 请教一些关于外挂的基础知识 0.00雪花

2015-10-21 21:28
5032
分析一个程序,知道了它调用ws2_32 send的地方的代码如下

0049A3CA  |.  50            push    eax
0049A3CB  |.  51            push    ecx
0049A3CC  |.  52            push    edx
0049A3CD  |.  A1 C07B5900   mov     eax, dword ptr [597BC0]
0049A3D2  |.  8B00          mov     eax, dword ptr [eax]
0049A3D4  |.  FFD0          call    eax                              ;  WS2_32.send

这个时候,eax 的值是 758f6f01,

我自己的外挂怎么才能调用这个程序已经加载的这个WS2_32.send,直接发送我想要发送的
数据包啊?

初学者真困难啊。
不知道有没有现成的一个框架:
注入目标程序,hook send函数,过滤保存一份需要的数据,然后在需要的时候,自己可以随时
再次发送这份数据。
求这样或者类似的框架啊。

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
免费 0
支持
分享
最新回复 (20)
雪    币: 1085
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
可能我说的不准确

比如 一个目标程序已经和服务器连接了tcp连接,并通过了身份验证,
是不是我的dll注入这个目标程序后,直接调用用ws2_32 的send就可以发送服务器到服务器了?
不需要connect什么的?
2015-10-21 22:03
0
雪    币: 5461
活跃值: (1410)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
你直接INLINE HOOK  WS2_32.send这个函数,做一下过滤就好了。
2015-10-21 22:11
0
雪    币: 216
活跃值: (39)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
果然很新手啊。。
2015-10-21 22:13
0
雪    币: 216
活跃值: (39)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
首先要注入到目标进程,然后hook api。。
注入目标进程方式很多。。
hook api方式也很多。。
2015-10-21 22:14
0
雪    币: 1085
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
各位达人,可否扔点简单的参考代码给瞧瞧啊。。。
谢谢先!
2015-10-21 23:13
0
雪    币: 1085
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
另外请教:如果自己准备数据的话,是否不需要hook了,直接注入目标进程,send即可?
2015-10-21 23:17
0
雪    币: 135
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
按照逆向逻辑分析,你在send下断点后,一层一层返回,直到出现明文数据包时候,那么相应的取得这个明文数据包参数的函数,就是所谓的游戏明文发包函数。

最后,你直接注入dll,自己按游戏明文包格式填写好,然后调用这个明文发包函数,其实很简单,考的是你的汇编和编程功底。祝你好运!!!!!
2015-10-21 23:26
0
雪    币: 96
活跃值: (36)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
同样初学,前几天写了一个简单的demon,比较原始,在多线程的时候调用send时候会有bug(但是足够简单可以说明原理了),lz可以看明白这个自己写个完善的,把多线程的问题解决掉,共享到这里,帮助后来更多的人
//定义的全局变量和类型
typedef int  (WINAPI *FunSend)(
	__in SOCKET s,
	__in_bcount(len) const char FAR * buf,
	__in int len,
	__in int flags
	);
//
BYTE byOldCode[5] = {0};  
BYTE byNewCode[5] = {0};
FunSend  lpOldFunSend = NULL;

//自己的函数定义
int  WINAPI MySend(
	__in SOCKET s,
	__in_bcount(len) const char FAR * buf,
	__in int len,
	__in int flags
	);


//在初始化时候
HMODULE hMod = ::LoadLibrary(_T("ws2_32.dll"));
lpOldFunSend = (FunSend)::GetProcAddress(hMod,"send");  
memcpy(byOldCode, lpOldFunSend, 5);
// 当前函数地址 + 5 + 跳转距离 = 跳转的地方 => 跳转的地方 - 当前函数地址 - 5
DWORD dwJmpDiff = (DWORD)MySend - (DWORD)send - 5;
byNewCode[0] = 0xe9;
*(DWORD*)&byNewCode[1] = dwJmpDiff;
//
DWORD dwOldProtect, dwTmp;
VirtualProtect(lpOldFunSend, 5, PAGE_READWRITE, &dwOldProtect);
memcpy(lpOldFunSend, byNewCode, 5);
VirtualProtect(lpOldFunSend, 5, dwOldProtect, &dwTmp); 


//跳到我的send
int  WINAPI MySend(
	__in SOCKET s,
	__in_bcount(len) const char FAR * buf,
	__in int len,
	__in int flags
	)
{
	DWORD dwOldProtect, dwTmp;
	VirtualProtect(lpOldFunSend, 5, PAGE_READWRITE, &dwOldProtect);   
	memcpy(lpOldFunSend, byOldCode, 5);
	VirtualProtect(lpOldFunSend, 5, dwOldProtect, &dwTmp);   
	//
	int nRet= send(s, buf, len, flags);
  DWORD dwLastError = GetLastError(),
	SOCKADDR_IN skAddr;
	int nLen=sizeof(skAddr);
	getpeername(s, (struct sockaddr *)&skAddr, &nLen);//得到远程IP地址和端口号
	char *szIP   =   inet_ntoa(skAddr.sin_addr);
	short sPort = ntohs(skAddr.sin_port);
	CString strLog;
	strLog.Format(_T("port:%d, ip:%s"), sPort, szIP);
	//
	VirtualProtect(lpOldFunSend, 5, PAGE_READWRITE, &dwOldProtect);   
	memcpy(lpOldFunSend, byNewCode, 5);
	VirtualProtect(lpOldFunSend, 5, dwOldProtect, &dwTmp); 
  SetLastError(dwLastError);
	return nRet;
}
2015-10-21 23:35
0
雪    币: 1392
活跃值: (4867)
能力值: ( LV13,RANK:240 )
在线值:
发帖
回帖
粉丝
10
提出两点建议
1不确定你使用关键段是不是为了想保护 写的时候不被打乱。如果是这样想的,那么在你的关键段起不到任何效果。
假设你初始化的时候未发生崩溃 当前send的地址上的数据是JMP XXX
第一个call send进入了你的Mysend 调用了EnterCS进入关键段,你正在进行memcpy前四个字节的时候,突然另外一个线程调用了一个call send,此时就会发生崩溃,call send的行为不是发生在你进入关键段之后,而是之前。

2调用send之后记得先funcerr=GetLastError()然后ret之前记得SetLastError(funcerr)
例如WSASend这类函数,有可能返回error,此时的状态为Pending
GetLastError可以得到PENDING状态。由于你函数在send之后执行了某些操作。比如getpeername函数会setlasterror将之前可能的PENDING状态清除掉。后续函数判断WSASend返回错误,调用GetLastError得到的却不是PENDING而是getpeername设置的OK。就会错误。
2015-10-22 08:29
0
雪    币: 1392
活跃值: (4867)
能力值: ( LV13,RANK:240 )
在线值:
发帖
回帖
粉丝
11
大清早为何总是会有特别想要回答问题的欲望呢?奇怪。。。
2015-10-22 08:30
0
雪    币: 96
活跃值: (36)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
12
谢谢热心人,
1. 的确临界区没啥用,所以可以删掉
2. 第二点真没有注意到这些细节,因为不是商业程序写的很随意,也就懒得改了,不过谢谢指正
2015-10-22 09:19
0
雪    币: 79
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
我也在写辅助框架 楼主求交流 q:84476063
2015-10-22 09:39
0
雪    币: 70
活跃值: (72)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
14
持续关注中~~
2015-10-22 09:54
0
雪    币: 35
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
32位下面的话,直接找到这个函数挂钩子就行了,只是要注意堆栈平衡;64位下的应用层hook没有搞过,不知道如何整,话说回来,为什么要去hook send函数呢,这个函数你hook住,我觉得分析起来要累死人啊,为什么不直接hook最上层的调用,我的意思是hook游戏本身的函数。
2015-10-22 13:00
0
雪    币: 1085
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
是不是64位下注入特麻烦啊,折腾了半天了,就是不成功

OpenProcess
VirtualAllocEx
WriteProcessMemory
GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA")
hThreadHandle=CreateRemoteThread(。。。

各个环节,包括最后 hThreadHandle的值都正常,dll就是一个测试的

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                                         )
{
        switch (ul_reason_for_call)
        {
        case DLL_PROCESS_ATTACH:
                MessageBoxA (0,"I'am a dll!","Dll_Inj",MB_OK |MB_ICONINFORMATION );
                while (1) {
                                        }
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
                break;
        }
        return TRUE;
}

死活看不到效果。

我是64位win7,vs2012,有人说 64位下注入,自己的程序必须是64位的,dll文件也必须是64位的
可是我测试了,还是不行。

是不是有什么特别需要注意的地方啊。。。
2015-10-22 17:28
0
雪    币: 39
活跃值: (52)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
呃,你不能在send这hook。。游戏在send之前是要加密的。你要找到明文包的发包地址。
2015-10-22 20:13
0
雪    币: 1085
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
谢谢各位大佬热心的回复。
我是学习阶段啊,想先把整个流程走一下,根本还没有到达“实用”的阶段。

新问题:
现在我已经把自己的dll注入目标进程了,如何调用目标进程已经加载的WS2_32 的send啊。。。
2015-10-22 22:09
0
雪    币: 1085
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
自己脑补了一个思路,
hook send,然后程序调用他的时候,就可以得到socket 的句柄,
然后自己直接send(socket,,,) 就可以了?
2015-10-23 10:29
0
雪    币: 96
活跃值: (36)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
20
我贴的代码不就是这样么!
2015-10-23 10:38
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
找到明文包再HOOK,而且8楼说的根本不可行,现在的游戏都是线程循环发包,那样做永远都是在一个死循环中,永远找不到明文发包
2015-10-26 14:24
0
游客
登录 | 注册 方可回帖
返回
//