LG纯R3注入龙之谷
注入的最大特点是, DragonNest.exe 找不到注入的模块
因为LG是使用自己的方法动态加载加载(非系统加载) InLG.dll 的资源dll INDNLG
如果龙之谷要扫描自身进程中的非法模块是难扫描到LG的注dll的
LG注入DLL的具体流程是
1 首先在登陆器 Hook CreateProcessW
7C802336 >/$- E9 D9F72084 jmp 00A11B14 ; Hook CreateProcessW
7C80233B |. 6A 00 push 0
7C80233D |. FF75 2C push [arg.10]
7C802340 |. FF75 28 push [arg.9]
7C802343 |. FF75 24 push [arg.8]
7C802346 |. FF75 20 push [arg.7]
7C802349 |. FF75 1C push [arg.6]
修复完被Hook的头五字节后,以挂起模式 CREATE_SUSPENDED 启动游戏 , 游戏启动后会暂停在那里
2读取INDNLG ,申请内存,写入游戏
图:InLG.dll的资源显示
写入到游戏后的内存
3初始化0x48的内存(主要获取API地址)
00A1188> 50 push eax
00A1188> E8 F4FEFFFF call 00A11788 ; 读取自身资源 写入到目标
00A1189> 8BF0 mov esi, eax
00A1189> 85F6 test esi, esi
00A1189> 75 0D jnz short 00A118A7
00A1189> 53 push ebx
00A1189> E8 D8E70100 call 00A30078 ; jmp 到 kernel32.CloseHandle
00A118A> 33C0 xor eax, eax
00A118A> E9 61020000 jmp 00A11B08
00A118A> 6A 48 push 48
00A118A> 57 push edi ; 获取地址,全部写入到 EDI
00A118A> E8 49E90100 call 00A301F8 ; 初始化 0x48 大小的结构体
00A118A> 8B55 FC mov edx, dword ptr ss:[ebp-4] ; 获取这些函数地址,保存到一个结构体中
00A118B> 8917 mov dword ptr ds:[edi], edx
00A118B> 8977 08 mov dword ptr ds:[edi+8], esi ; 存放写入资源的首地址
00A118B> 8B0D 3C4DA300 mov ecx, dword ptr ds:[A34D3C]
00A118B> 8B41 50 mov eax, dword ptr ds:[ecx+50]
00A118C> 8947 04 mov dword ptr ds:[edi+4], eax ; 下面是获取一系列函数地址
00A118C> 68 7411A300 push 0A31174 ; UNICODE "kernel32.dll"
00A118C> E8 5FE80100 call 00A3012C ; jmp 到 kernel32.GetModuleHandleW
00A118C> 8BF0 mov esi, eax
00A118C> 68 8E11A300 push 0A3118E ; ASCII "VirtualAllocEx"
00A118D> 56 push esi
00A118D> E8 5EE80100 call 00A30138 ; jmp 到 kernel32.GetProcAddress
00A118D> 8947 14 mov dword ptr ds:[edi+14], eax
00A118D> 68 9D11A300 push 0A3119D ; ASCII "VirtualFreeEx"
00A118E> 56 push esi
00A118E> E8 50E80100 call 00A30138 ; jmp 到 kernel32.GetProcAddress
00A118E> 8947 18 mov dword ptr ds:[edi+18], eax
00A118E> 68 AB11A300 push 0A311AB ; ASCII "RtlMoveMemory"
00A118F> 56 push esi
4 写入 0x400 函数
0013D92C 0000023C |hProcess = 0000023C (窗口)
0013D930 001D0000 |Address = 1D0000
0013D934 00A11578 |Buffer = 00A11578
0013D938 00000400 |BytesToWrite = 400 (1024.)
0013D93C 00000000 \pBytesWritten = NULL
00A11578 55 push ebp
00A11579 8BEC mov ebp, esp
00A1157B 83C4 D0 add esp, -30
00A1157E 53 push ebx
00A1157F 56 push esi
00A11580 57 push edi
00A11581 8B75 08 mov esi, dword ptr ss:[ebp+8]
00A11584 85F6 test esi, esi
00A11586 74 0C je short 00A11594
00A11588 837E 08 00 cmp dword ptr ds:[esi+8], 0
00A1158C 74 06 je short 00A11594
00A1158E 837E 14 00 cmp dword ptr ds:[esi+14], 0
00A11592 75 07 jnz short 00A1159B
00A11594 33C0 xor eax, eax
00A11596 E9 E1010000 jmp 00A1177C
00A1159B 8B56 08 mov edx, dword ptr ds:[esi+8]
00A1159E 8955 FC mov dword ptr ss:[ebp-4], edx
00A115A1 8B4D FC mov ecx, dword ptr ss:[ebp-4]
00A115A4 8B41 3C mov eax, dword ptr ds:[ecx+3C]
00A115A7 0345 FC add eax, dword ptr ss:[ebp-4]
00A115AA 8945 F8 mov dword ptr ss:[ebp-8], eax
00A115AD 8B55 F8 mov edx, dword ptr ss:[ebp-8]
00A115B0 8B5A 50 mov ebx, dword ptr ds:[edx+50]
5 再写入 0x200函数
0013D92C 0000023C |hProcess = 0000023C (窗口)
0013D930 001E0000 |Address = 1E0000
0013D934 00A11528 |Buffer = 00A11528
0013D938 00000200 |BytesToWrite = 200 (512.)
00A11528 55 push ebp ; +0x200函数
00A11529 8BEC mov ebp, esp
00A1152B 53 push ebx
00A1152C 8B5D 08 mov ebx, dword ptr ss:[ebp+8]
00A1152F 85DB test ebx, ebx
00A11531 74 2A je short 00A1155D
00A11533 837B 08 00 cmp dword ptr ds:[ebx+8], 0
00A11537 74 24 je short 00A1155D
00A11539 53 push ebx
00A1153A FF53 0C call dword ptr ds:[ebx+C]
00A1153D 68 00400000 push 4000
00A11542 6A 00 push 0
00A11544 8B43 08 mov eax, dword ptr ds:[ebx+8]
00A11547 50 push eax
00A11548 6A FF push -1
00A1154A FF53 18 call dword ptr ds:[ebx+18]
00A1154D 68 00400000 push 4000
00A11552 6A 00 push 0
00A11554 8B53 0C mov edx, dword ptr ds:[ebx+C]
6 写入0x48 带有API地址的结构体,修改Context改变游戏执行流程,
00A11AF8 E8 25E70100 call 00A30222 ; SetThreadContext
00A11AFD 53 push ebx
00A11AFE E8 75E50100 call 00A30078 ;
00A11B03 B8 01000000 mov eax, 1
00A11A5F E8 30E80100 call 00A30294 ; 写入 0x48 结构体 信息(API地址)
00A11A64 C785 28FDFFFF 0>mov dword ptr ss:[ebp-2D8], 10001
00A11A6E 8D8D 28FDFFFF lea ecx, dword ptr ss:[ebp-2D8]
00A11A74 51 push ecx
00A11A75 8B45 0C mov eax, dword ptr ss:[ebp+C]
00A11A78 50 push eax
00A11A79 E8 DEE60100 call 00A3015C ; 获取Context
00A11A7E 6A 32 push 32
00A11A80 68 6415A100 push 0A11564 ; ASCII "h33"
00A11A85 8D95 F4FCFFFF lea edx, dword ptr ss:[ebp-30C]
00A11A8B 52 push edx
00A11A8C E8 5BE70100 call 00A301EC ; jmp 到 ntdll.RtlMoveMemory
00A11A91 8D8D F5FCFFFF lea ecx, dword ptr ss:[ebp-30B]
00A11A97 8B85 E0FDFFFF mov eax, dword ptr ss:[ebp-220]
00A11A9D 8901 mov dword ptr ds:[ecx], eax
00A11A9F 8D95 FBFCFFFF lea edx, dword ptr ss:[ebp-305]
00A11AA5 8B4D F4 mov ecx, dword ptr ss:[ebp-C]
00A11AA8 890A mov dword ptr ds:[edx], ecx ; API 结构0x48
00A11AAA 8D85 00FDFFFF lea eax, dword ptr ss:[ebp-300]
00A11AB0 8B55 F8 mov edx, dword ptr ss:[ebp-8] ; 0X200函数地址
00A11AB3 8910 mov dword ptr ds:[eax], edx
00A11AB5 6A 40 push 40
00A11AB7 68 00100000 push 1000
14 > 55 push ebp
15 > 8BEC mov ebp, esp
17 > 83C4 D0 add esp, -30
1A > 53 push ebx
1B > 56 push esi
1C > 57 push edi
1D > 8B75 08 mov esi, dword ptr ss:[ebp+8]
20 > 85F6 test esi, esi
22 > 74 0C je short 0013D97C
24 > 837E 08 00 cmp dword ptr ds:[esi+8], 0
28 > 74 06 je short 0013D97C
00A11ABC 6A 32 push 32
写入入口点函数代码,
$ ==> > 68 0507817C push 7C810705 ; 返回地址
5 > 60 pushad
6 > 68 00001F00 push 1F0000
B > B8 00001E00 mov eax, 1E0000
10 > FFD0 call eax
12 > 61 popad
13 > C3 retn ; push jmp
2A > 837E 14 00 cmp dword ptr ds:[esi+14], 0
2E > 75 07 jnz short 0013D983
30 > 33C0 xor eax, eax
登陆器在写入全部数据修改Context后
先 pushad保存现场
然后调用 call 0x1e0000 初始化自己的dll
最后popad还原
ret 交还游戏
如果要写挂注入GPK保护下的龙之谷,可以直接在Hook CreateProcessW 后注入 ,
当然隐藏性就没LG的好了