2008年写的!并没有销售过 大家可放心看。里面包含了2个RadASM 和 MASMPlus 的工程文件,打开MainDll.app 可直接编译,当然你要配置一下masm的路径,直接打开Main.exe可选择系统自带的 calc.exe计算器 启动后会自动呼出dll,由于现在没有服务器,为了方便直接看已经把里面服务器通信的几个小地方删除,服务器端也是用masm写的,注册和充值我是用.net实现. 用户直接点击‘登录’就可以看到所有界面 。资源文件rs用vc6.0以上的工具可查看。
另外,我自己的一些经历,历程想写下来 链接是:
http://bbs.pediy.com/showthread.php?p=1308408#post1308408
有兴趣的朋友请支持一下。谢谢 部分代码有:
.data?
hGoodsFile dword ?;data.dat文件句柄
hGoodsMap dword ?;物品的map
lpGoodsView dword ?
hGoodsFile2 dword ?;data2.dat文件句柄
hGoodsMap2 dword ?;物品的map
lpGoodsView2 dword ?
hGoodsFile3 dword ?;怪物
hGoodsMap3 dword ?;怪物的map
lpGoodsView3 dword ?
szGoodsFileBuf BYTE MAX_PATH DUP(?);sell.txt文件缓存
szGoodCwpBuf BYTE MAX_PATH DUP(?);save.data文件缓存
.data
szGoodsFile byte 'sell.txt',0;sell.txt文件 装有不要扔掉的物品数据
szGoodsCwp byte 'save.txt',0;save.data文件 指定存入仓库的物品名字
szGoodsS byte '无限回城符,素炒竹肉,家常四季豆,炒豌豆角,蒜茸生菜,玉笛谁家听落梅',0;默认存放不扔掉的物品 每个字符之间用空格分隔,最后一个以0结尾
szSaveS byte '小块玄晶碎片(1级玄晶),玄晶碎片(2级玄晶),小块玄晶残片(3级玄晶),玄晶残片(4级玄晶),未雕琢的玄晶(5级玄晶),有裂痕的玄晶(6级玄晶),普通的玄晶(7级玄晶)',0
.code
;查找指定字符串 没有找到返回0 找到返回查找到的字符后面的地址
;_FillStart主块开始地址 _Search要查找的字符串
_SearchString proc _FillStart,_Search
local @SearchSize,@FillSize,@return ;@SearchSize;要找查的大小 @FillSize主块的大小
pushad
invoke lstrlen,_Search
mov @SearchSize,eax;要查找的大小
invoke lstrlen,_FillStart
mov @FillSize,eax;主块大小
mov @return,0
.if eax
mov esi,_Search;要查找的字符串地址
mov edi,_FillStart ;主块开始地址
mov ecx,@FillSize;主块的大小
mov ebx,@SearchSize;要查找的大小
S1:
or ecx,ecx
jz _Ret;读取到的已经为0没有查找性了
or ebx,ebx
jz _Ret;要比较的为0也没有比较性了
cmp ecx,ebx
jb _Ret;读取到的比要查找到的还要小 退出
mov al,[esi]
cmp al,[edi]
jz S2;查到的第一个字符相等,开始进入第二阶段
dec ecx;读取的-1 表示比较完一次
inc edi;读取的字符向前移动
jmp S1;
S2:;第一阶段通过后进入此阶段
dec ebx
dec ecx
inc esi
inc edi
or ebx,ebx
jz findf;表示已经查找到了 ;这个需要在下面的or ecx,ecx的上面。不然如果字符在最后的话会不正确的
or ecx,ecx
jz _Ret;读取到的已经为0没有查找性了
cmp ecx,ebx
jb _Ret;读取到的比要查找到的还要小 退出
mov al,[esi]
cmp al,[edi]
jz S2
S3:;到了这个阶段表示在第二阶段也没有找到
mov esi,_Search
mov ebx,@SearchSize
jmp S1
findf:;
mov eax,@FillSize ;主块的大小
sub eax,ecx ;主块的大小-还没有读取的主块大小=已经读取的主块大小
add eax,_FillStart;已经读取的主块大小+主块起始地址=查找到的字符后面的地址
mov @return,eax;查找到的字符后面的地址
jmp _Ret
.endif
_Ret:
popad
mov eax,@return
ret
_SearchString endp
;打开或创建文件,(文件不存在将要创建文件同时放入默认要保存的物品)
_CreateGoods proc
local @buf
pushad
invoke lstrcpy,addr szGoodsFileBuf,addr szDllPath
invoke lstrcat,addr szGoodsFileBuf,addr szGoodsFile;取得sell.txt全路径
invoke CreateFile,addr szGoodsFileBuf,GENERIC_READ OR GENERIC_WRITE,FILE_SHARE_READ OR FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL
.if eax==INVALID_HANDLE_VALUE;如果文件不存在则创建此文件
invoke CreateFile,addr szGoodsFileBuf,GENERIC_WRITE OR GENERIC_READ,FILE_SHARE_READ OR FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL;打开/创建文件
.if eax !=INVALID_HANDLE_VALUE
mov hGoodsFile,eax
invoke CreateFileMapping,hGoodsFile,NULL,PAGE_READWRITE,0,4096*50,NULL
mov hGoodsMap,eax
invoke MapViewOfFile,hGoodsMap,FILE_MAP_READ OR FILE_MAP_WRITE,0,0,0
mov lpGoodsView,eax
;因为文件才创建 所以我们先写入自己预设一点数据
invoke lstrcpy,lpGoodsView,addr szGoodsS
invoke FlushViewOfFile,lpGoodsView,sizeof szGoodsS
.endif
.else;文件存在则打开map
mov hGoodsFile,eax
invoke CreateFileMapping,hGoodsFile,NULL,PAGE_READWRITE,0,4096*50,NULL
mov hGoodsMap,eax
invoke MapViewOfFile,hGoodsMap,FILE_MAP_READ OR FILE_MAP_WRITE,0,0,0
mov lpGoodsView,eax
.endif
invoke lstrcpy,addr szGoodCwpBuf,addr szDllPath
invoke lstrcat,addr szGoodCwpBuf,addr szGoodsCwp;取得sell.txt全路径
;仓库物品
invoke CreateFile,addr szGoodCwpBuf,GENERIC_READ OR GENERIC_WRITE,FILE_SHARE_READ OR FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL
.if eax==INVALID_HANDLE_VALUE;如果文件不存在则创建此文件
invoke CreateFile,addr szGoodCwpBuf,GENERIC_WRITE OR GENERIC_READ,FILE_SHARE_READ OR FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL;打开/创建文件
.if eax !=INVALID_HANDLE_VALUE
mov hGoodsFile2,eax
invoke CreateFileMapping,hGoodsFile2,NULL,PAGE_READWRITE,0,4096*50,NULL
mov hGoodsMap2,eax
invoke MapViewOfFile,hGoodsMap2,FILE_MAP_READ OR FILE_MAP_WRITE,0,0,0
mov lpGoodsView2,eax
;因为文件才创建 所以我们先写入自己预设一点数据
invoke lstrcpy,lpGoodsView2,addr szSaveS
invoke FlushViewOfFile,lpGoodsView2,sizeof szSaveS
.endif
.else;文件存在则打开map
mov hGoodsFile2,eax
invoke CreateFileMapping,hGoodsFile2,NULL,PAGE_READWRITE,0,4096*50,NULL
mov hGoodsMap2,eax
invoke MapViewOfFile,hGoodsMap2,FILE_MAP_READ OR FILE_MAP_WRITE,0,0,0
mov lpGoodsView2,eax
.endif
popad
ret
_CreateGoods endp
;释放已打开的资源
_goodsClose proc
pushad
invoke UnmapViewOfFile,lpGoodsView
invoke CloseHandle,hGoodsMap
invoke CloseHandle,hGoodsFile
invoke UnmapViewOfFile,lpGoodsView2
invoke CloseHandle,hGoodsMap2
invoke CloseHandle,hGoodsFile2
popad
ret
_goodsClose endp
;向List控件写入不需要丢弃的物品 (不扔掉的物品 每个字符之间用,分隔,最后一个以0结尾)
_readGoods proc
local @buf[30]:BYTE
pushad
invoke SendDlgItemMessage,hWin1,IDC_LIST1,LB_RESETCONTENT,0,0;首先删除列表里面所有的项目
mov esi,lpGoodsView
lea edi,@buf
mov edx,0;用这个来标识是否有数据
gs1:
mov al,','
cmp BYTE ptr [esi],0
je gs2 ;字符如果为0了表示到了结尾 然后看edx中是否有数据有就取
cmp [esi],al
jz gs2;如果数据为','则表示这句完了可以插入控件了
mov al,[esi]
mov [edi],al
inc esi
inc edi
inc edx
jmp gs1
gs2:
inc esi
mov BYTE ptr [edi],0;把在整个字符最后面插入个0
.if edx
invoke SendDlgItemMessage,hWin1,IDC_LIST1,LB_INSERTSTRING,-1,addr @buf
.else
jmp _Ret
.endif
lea edi,@buf;把edi又设置为开头重新取新数据
mov edx,0
jmp gs1
_Ret:
popad
ret
_readGoods endp
;保存新物品名称进文件里面,同时更新了list控件
_addGoods proc
local @buf[256]:BYTE
invoke GetDlgItemText,hWin1,IDC_ADDGOODS,addr @buf,sizeof @buf
.if eax;eax是读取到的名字长度。不为0就表示是字符喽
;查找指定字符串 没有找到返回0 找到返回查找到的字符后面的地址
invoke _SearchString,lpGoodsView,addr @buf;
.if eax==0;如果没有相等的就添加
invoke lstrlen,lpGoodsView
mov esi,eax
add esi,lpGoodsView;指向最后的字符0
.if eax ;这里的eax是指的总字符的长度,如果长度不为0才需要添加',' 如果为0表示是第一个字符,就不需要添加','了
mov al,','
mov [esi],al;设置最后一个为','
inc esi
.endif
invoke lstrcpy,esi,addr @buf;这里esi是指向了最终的0
invoke _readGoods;添加了则更新一次控件
invoke SendDlgItemMessage,hWin1,IDC_LIST1,LB_GETCOUNT,0,0;选中最后添加的一项
DEC eax;选中是基于0
invoke SendDlgItemMessage,hWin1,IDC_LIST1,LB_SETCURSEL,eax,0
.else
invoke MessageBox,hWin1,addr szErrGed,addr szTitle,MB_OK OR MB_ICONINFORMATION
.endif
.else
invoke MessageBox,hWin1,addr szErrAdd,addr szTitle,MB_OK OR MB_ICONINFORMATION
.endif
ret
_addGoods endp
;在文件里删除指定的物品名称,同时更新了list控件
_delGoods proc
local @buf[256]:BYTE
invoke SendDlgItemMessage,hWin1,IDC_LIST1,LB_GETCURSEL,0,0
.if eax!= LB_ERR;eax是当前选中的索引 如果没有选中则是返回 LB_ERR
mov ebx,eax
invoke SendDlgItemMessage,hWin1,IDC_LIST1,LB_GETTEXT,ebx,addr @buf
;查找指定字符串 没有找到返回0 找到返回查找到的字符后面的地址
invoke _SearchString,lpGoodsView,addr @buf;
.if eax!=0;查找到了字符,开始移除
mov esi,eax;指向该字符后面的从','开始的
mov edi,eax;指向该字符后面的从','开始的
invoke lstrlen,addr @buf;取得当前文字的长度
inc eax;再+1 因为还有一个','需要去掉
.while eax;把这段字符都设置为0
mov BYTE ptr [edi],0
dec eax
dec edi
.endw
inc esi;因为esi指向的当前','被设为0 所以要增加一下指向后面
inc edi;edi已经被上面的设置指向了前面的',' 需要保留一个','所以也增加一次
invoke lstrlen,esi;取后面的长度
.while eax;有长度就复制过去
mov cl,[esi]
mov [edi],cl
mov BYTE ptr [esi],0;然后本当前的就不需要保留 删除掉
inc esi
inc edi
dec eax
.endw
invoke lstrcat,lpGoodsView,esi;合并成新的
invoke lstrlen,lpGoodsView;如果最后一个字符是',' 则去掉 在这防止 出错
.if eax
add eax,lpGoodsView
dec eax
mov bl,','
cmp BYTE ptr [eax],bl
jnz @F
mov BYTE ptr [eax],0
@@:
.endif
invoke _readGoods;添加了则更新一次控件
.endif
.else
invoke MessageBox,hWin1,addr szErrSel,addr szTitle,MB_OK OR MB_ICONINFORMATION
.endif
ret
_delGoods endp ;向List控件写入不需要丢弃的物品 (不扔掉的物品 每个字符之间用,分隔,最后一个以0结尾)
_readGoods2 proc
local @buf[30]:BYTE
pushad
invoke SendDlgItemMessage,hWin1,IDC_LIST2,LB_RESETCONTENT,0,0;首先删除列表里面所有的项目
mov esi,lpGoodsView2
lea edi,@buf
mov edx,0;用这个来标识是否有数据
gs1:
mov al,','
cmp BYTE ptr [esi],0
je gs2 ;字符如果为0了表示到了结尾 然后看edx中是否有数据有就取
cmp [esi],al
jz gs2;如果数据为','则表示这句完了可以插入控件了
mov al,[esi]
mov [edi],al
inc esi
inc edi
inc edx
jmp gs1
gs2:
inc esi
mov BYTE ptr [edi],0;把在整个字符最后面插入个0
.if edx
invoke SendDlgItemMessage,hWin1,IDC_LIST2,LB_INSERTSTRING,-1,addr @buf
.else
jmp _Ret
.endif
lea edi,@buf;把edi又设置为开头重新取新数据
mov edx,0
jmp gs1
_Ret:
popad
ret
_readGoods2 endp
;保存新物品名称进文件里面,同时更新了list控件
_addGoods2 proc
local @buf[256]:BYTE
invoke GetDlgItemText,hWin1,IDC_ADDGOODS2,addr @buf,sizeof @buf
.if eax;eax是读取到的名字长度。不为0就表示是字符喽
;查找指定字符串 没有找到返回0 找到返回查找到的字符后面的地址
invoke _SearchString,lpGoodsView2,addr @buf;
.if eax==0;如果没有相等的就添加
invoke lstrlen,lpGoodsView2
mov esi,eax
add esi,lpGoodsView2;指向最后的字符0
.if eax ;这里的eax是指的总字符的长度,如果长度不为0才需要添加',' 如果为0表示是第一个字符,就不需要添加','了
mov al,','
mov [esi],al;设置最后一个为','
inc esi
.endif
invoke lstrcpy,esi,addr @buf;这里esi是指向了最终的0
invoke _readGoods2;添加了则更新一次控件
invoke SendDlgItemMessage,hWin1,IDC_LIST2,LB_GETCOUNT,0,0;选中最后添加的一项
DEC eax;选中是基于0
invoke SendDlgItemMessage,hWin1,IDC_LIST2,LB_SETCURSEL,eax,0
.else
invoke MessageBox,hWin1,addr szErrGed,addr szTitle,MB_OK OR MB_ICONINFORMATION
.endif
.else
invoke MessageBox,hWin1,addr szErrAdd,addr szTitle,MB_OK OR MB_ICONINFORMATION
.endif
ret
_addGoods2 endp
;在文件里删除指定的物品名称,同时更新了list控件
_delGoods2 proc
local @buf[256]:BYTE
invoke SendDlgItemMessage,hWin1,IDC_LIST2,LB_GETCURSEL,0,0
.if eax!= LB_ERR;eax是当前选中的索引 如果没有选中则是返回 LB_ERR
mov ebx,eax
invoke SendDlgItemMessage,hWin1,IDC_LIST2,LB_GETTEXT,ebx,addr @buf
;查找指定字符串 没有找到返回0 找到返回查找到的字符后面的地址
invoke _SearchString,lpGoodsView2,addr @buf;
.if eax!=0;查找到了字符,开始移除
mov esi,eax;指向该字符后面的从','开始的
mov edi,eax;指向该字符后面的从','开始的
invoke lstrlen,addr @buf;取得当前文字的长度
inc eax;再+1 因为还有一个','需要去掉
.while eax;把这段字符都设置为0
mov BYTE ptr [edi],0
dec eax
dec edi
.endw
inc esi;因为esi指向的当前','被设为0 所以要增加一下指向后面
inc edi;edi已经被上面的设置指向了前面的',' 需要保留一个','所以也增加一次
invoke lstrlen,esi;取后面的长度
.while eax;有长度就复制过去
mov cl,[esi]
mov [edi],cl
mov BYTE ptr [esi],0;然后本当前的就不需要保留 删除掉
inc esi
inc edi
dec eax
.endw
invoke lstrcat,lpGoodsView2,esi;合并成新的
invoke lstrlen,lpGoodsView2;如果最后一个字符是',' 则去掉 在这防止 出错
.if eax
add eax,lpGoodsView2
dec eax
mov bl,','
cmp BYTE ptr [eax],bl
jnz @F
mov BYTE ptr [eax],0
@@:
.endif
invoke _readGoods2;添加了则更新一次控件
.endif
.else
invoke MessageBox,hWin1,addr szErrSel,addr szTitle,MB_OK OR MB_ICONINFORMATION
.endif
ret
_delGoods2 endp ;硬盘加密算法
_DriveU proc _string,_num,_key;_string:需要加密的地址 _num:加密的数据大小 _key密钥地址
local @js
VM_START
pushad
mov esi,_string
; sub BYTE ptr [esi+0],1
; add BYTE ptr [esi+1],2
; sub BYTE ptr [esi+2],1
; add BYTE ptr [esi+3],2
; sub BYTE ptr [esi+4],2
; sub BYTE ptr [esi+5],1
; add BYTE ptr [esi+6],1
; sub BYTE ptr [esi+7],1
; add BYTE ptr [esi+8],1
; add BYTE ptr [esi+9],1
mov eax,[esi]
xchg eax,[esi+8]
xchg eax,[esi+2]
xchg eax,[esi]
xchg eax,[esi+4]
xchg eax,[esi+2]
xchg eax,[esi+4]
xchg eax,[esi+6]
invoke lstrlen,_string
mov ecx,eax
mov esi,_string
; sub BYTE ptr [esi+eax-1],1
; add BYTE ptr [esi+eax-2],1
; sub BYTE ptr [esi+eax-3],1
; add BYTE ptr [esi+eax-4],1
; add BYTE ptr [esi+eax-5],1
; sub BYTE ptr [esi+eax-6],1
; add BYTE ptr [esi+eax-7],1
; sub BYTE ptr [esi+eax-8],1
; add BYTE ptr [esi+eax-9],1
mov ebx,[esi]
xchg ebx,[esi+eax-8]
xchg ebx,[esi+eax-4]
xchg ebx,[esi+eax-6]
xchg ebx,[esi+2]
.while ecx
mov @js,0
.if BYTE ptr [esi]=='7' || BYTE ptr [esi]=='6'
mov BYTE ptr [esi],'r'
.endif
.if BYTE ptr [esi]>='2' && BYTE ptr [esi]<='7'
mov @js,1
.endif
.if BYTE ptr [esi]>='c' && BYTE ptr [esi]<='x'
mov @js,1
.endif
.if BYTE ptr [esi]>='C' && BYTE ptr [esi]<='X'
mov @js,1
.endif
.if @js
mov eax,ecx
cdq
mov ebx,2
div ebx
.if edx
sub BYTE ptr [esi],2
.else
add BYTE ptr [esi],1
.endif
.endif
inc esi
dec ecx
.endw
popad
VM_END
ret
_DriveU endp
;Tea加密算法
;
_EncryptionTea proc uses ebx edi esi _lpData,_lpNum,_keyStr ;加密 _lpData数据地址 _lpNum需加密数据大小 _keyStr加密数据
LOCAL @v0,@v1 ;@v1需要加密的低位 @v0需要加密的高位
LOCAL @y,@z ;;@y需要加密的低位 ;@z需要加密的高位
LOCAL @Sum,@Delta
LOCAL @a_,@b_,@c_,@d_;;加密密钥是16字节 分别给@a_ @b_ @c_ @d_
LOCAL @_Count ;轮数
LOCAL @num;需要加密的次数。利用当前数据长度除4得到
LOCAL @jmcs;加密数据在while里面是第几次
LOCAL @zz;指针
LOCAL @number;@number当前数据的大小
mov edi,_keyStr ;加密密钥是16字节 分别给@a_ @b_ @c_ @d_
mov eax,dword ptr [edi+0]
mov @a_,eax
mov eax,dword ptr [edi+4]
mov @b_,eax
mov eax,dword ptr [edi+8]
mov @c_,eax
mov eax,dword ptr [edi+12]
mov @d_,eax
mov eax,_lpNum
shr eax,3 ;长度除8(byte)
inc eax
shl eax,3 ;这3句的功能是实现不管长度为多少总是8的整数倍
mov @number,eax
mov eax,@number
xor edx,edx
mov ecx,8
div ecx
mov @num,eax
mov @jmcs,0
push _lpData
pop @zz
.while @num
mov @_Count,32 ;32轮
mov @Sum,0 ;初始一些变量值
mov @Delta,9E3779B9h
.if @jmcs;加密次数不是第一次。则每次数据+8 指向后面的
add @zz,8
.endif
mov edi,@zz ;edi=刚分析的内存里面是需要加密的数据
mov eax,dword ptr [edi+0]
mov @v0,eax ;@v0需要加密的高位
mov eax,dword ptr [edi+4]
mov @v1,eax ;@v1需要加密的低位
mov eax,@v0
mov @y,eax ;@y需要加密的低位
mov eax,@v1
mov @z,eax ;@z需要加密的高位
.while @_Count > 0
mov eax,@Sum ; Sum <- Sum + Delata
add eax,@Delta
mov @Sum,eax
;----------------------------
;y <- y +(((z<<4)+a)^(z+Sum)^((z>>5)+b))
mov eax,@z ; z << 4 --> eax
shl eax,4
add eax,@a_ ; a + (z<<4) --> ebx
mov ecx,@z ; ( z >> 5) + b --> ecx
shr ecx,5
add ecx,@b_
mov ebx,@z ; z + sum
add ebx,@Sum
xor eax,ebx
xor eax,ecx
add eax,@y
mov @y,eax
;------------------------------
;z <- z +(((y<<4)+c)^(y+Sum)^((y>>5)+d))
mov eax,@y ;(y << 4)+c --> eax
shl eax,4
add eax,@c_
mov ebx,@y ; y + sum --> ebx
add ebx,@Sum
mov ecx,@y ; Sum ^ (y>>5) --> ecx
shr ecx,5
add ecx,@d_
xor eax,ebx ; eax+ebx+ecx+d+z --> z
xor eax,ecx
add eax,@z
mov @z,eax
dec @_Count
.endw
mov eax,@y
xchg al,ah
rol eax,16
xchg al,ah
mov @v0,eax
mov eax,@z
xchg al,ah
rol eax,16
xchg al,ah
mov @v1,eax
mov edi,@zz;保存数据
mov eax,@v0
mov dword ptr [edi+0],eax
mov eax,@v1
mov dword ptr [edi+4],eax
inc @jmcs;每计算一次此数据加1一次
dec @num;此数据减1
.endw
VM_START
mov esi,_lpData;在加密基础上再做了一个简单的加密运算
mov ecx,_lpNum
.while ecx
xor BYTE ptr [esi],0A9H
inc esi
dec ecx
.endw
VM_END
ret
_EncryptionTea endp
;
;
;Tea解密算法
_DecryptionTea proc uses ebx edi esi _lpData,_lpNum,_keyStr ;解密 _lpData数据地址 _lpNum需加密数据大小 _keyStr加密数据
LOCAL @v0,@v1
LOCAL @y,@z
LOCAL @Sum,@Delta
LOCAL @a_,@b_,@c_,@d_
LOCAL @_Count ;轮数
LOCAL @num;需要加密的次数。利用当前数据长度除4得到
LOCAL @jmcs;加密数据在while里面是第几次
LOCAL @zz;指针
LOCAL @number;@number当前数据的大小
VM_START
mov esi,_lpData;在加密基础上再做了一个简单的加密运算
mov ecx,_lpNum
.while ecx
xor BYTE ptr [esi],012H
inc esi
dec ecx
.endw
VM_END
mov edi,_keyStr
mov eax,dword ptr [edi+0]
mov @a_,eax
mov eax,dword ptr [edi+4]
mov @b_,eax
mov eax,dword ptr [edi+8]
mov @c_,eax
mov eax,dword ptr [edi+12]
mov @d_,eax
mov eax,_lpNum
shr eax,3 ;长度除8(byte)
inc eax
shl eax,3 ;这3句的功能是实现不管长度为多少总是8的整数倍
mov @number,eax
mov eax,@number
xor edx,edx
mov ecx,8
div ecx
mov @num,eax
mov @jmcs,0
push _lpData
pop @zz
.while @num
mov @_Count,32 ;32轮
mov @Sum,0c6ef3720h ;初始一些变量值
mov @Delta,09e3779b9h
.if @jmcs;加密次数不是第一次。则每次数据+8 指向后面的
add @zz,8
.endif
mov edi,@zz
mov eax,dword ptr [edi+0]
xchg al,ah
rol eax,16
xchg al,ah
mov @v0,eax
mov eax,dword ptr [edi+4]
xchg al,ah
rol eax,16
xchg al,ah
mov @v1,eax
mov eax,@v0
mov @y,eax
mov eax,@v1
mov @z,eax
.while @_Count > 0
;----------------------------
;z <- z - (((y<<4) + c)^(y + Sum)^((y>>5) + d))
mov eax,@y ; (y << 4) + c--> eax
shl eax,4
add eax,@c_
mov ebx,@y ; y + sum --> ebx
add ebx,@Sum
mov ecx,@y ; Sum ^ ( y >> 5) --> ecx
shr ecx,5
add ecx,@d_
xor eax,ebx ; eax +ebx + ecx + d -->eax
xor eax,ecx
mov ebx,eax
mov eax,@z
sub eax,ebx
mov @z,eax
;------------------------------
;y <- y - ((z<<4) + a)^(z + Sum)^((z>>5) + b))
mov eax,@z ;z << 4 --> eax
shl eax,4
add eax,@a_
mov ebx,@z ;z + Sum --> ebx
add ebx,@Sum
mov ecx,@z ; (z>>5)+ b--> ecx
shr ecx,5
add ecx,@b_
xor eax,ebx ;y-(eax^ebx^ecx) --> ebx
xor eax,ecx
mov ebx,eax
mov eax,@y
sub eax,ebx
mov @y,eax
mov eax,@Sum ;sum <-- sum - Delata
sub eax,@Delta
mov @Sum,eax
dec @_Count
.endw
mov eax,@y
mov @v0,eax
mov eax,@z
mov @v1,eax
mov edi,@zz
mov eax,@v0
mov dword ptr [edi+0],eax
mov eax,@v1
mov dword ptr [edi+4],eax
inc @jmcs;每计算一次此数据加1一次
dec @num;此数据减1
.endw
ret
_DecryptionTea endp
;
_EncryptionU proc _string,_num,_key;_string:需要加密的地址 _num:加密的数据大小 _key密钥地址
pushad
mov eax,_num
shr eax,3 ;长度除8(byte)
inc eax
shl eax,3 ;这3句的功能是实现不管长度为多少总是8的整数倍
mov ecx,eax
mov esi,_key
mov bl,[esi]
mov esi,_string
s1:
xor BYTE ptr [esi],bl
inc bl
inc esi
loop s1
popad
ret
_EncryptionU endp _DecryptionU proc _string,_num,_key;_string:需要加密的地址 _num:加密的数据大小 _key密钥地址
pushad
mov eax,_num
shr eax,3 ;长度除8(byte)
inc eax
shl eax,3 ;这3句的功能是实现不管长度为多少总是8的整数倍
mov ecx,eax
mov esi,_key
mov bl,[esi]
mov esi,_string
s1:
xor BYTE ptr [esi],bl
inc bl
inc esi
loop s1
popad
ret
_DecryptionU endp
;老的硬盘加密算法
_DriveULL proc _string,_num,_key;_string:需要加密的地址 _num:加密的数据大小 _key密钥地址
VM_START
pushad
mov esi,_string
add BYTE ptr [esi+0],1
sub BYTE ptr [esi+1],2
add BYTE ptr [esi+2],1
sub BYTE ptr [esi+3],1
add BYTE ptr [esi+4],2
add BYTE ptr [esi+5],1
add BYTE ptr [esi+6],1
sub BYTE ptr [esi+7],2
sub BYTE ptr [esi+8],1
sub BYTE ptr [esi+9],1
mov eax,[esi]
xchg eax,[esi+4]
xchg eax,[esi+1]
xchg eax,[esi+8]
xchg eax,[esi+2]
xchg eax,[esi]
xchg eax,[esi+4]
xchg eax,[esi+1]
popad
VM_END
ret
_DriveULL endp
;=========================花指令===========================================
_JmpCode macro Text,ECode
mov [esp-1Ch],eax
mov [esp-20h],ebp
call @F
db 0C3h ; ret
db 069h
@@:
xchg ebp,[esp]
pop eax
mov eax,@B
sub eax,2
sub ebp,eax
Call @F
db 83h
@@:
xchg eax,[esp]
call @F
db 88h,31h
@@:
pop eax
lea eax,Text
add eax,ebp
mov [esp],eax
mov eax,[esp-18h]
mov ebp,[esp-1Ch]
db 0C3h ; ret
db ECode
endm
;使用的时候非常简单,象下面用宏就是
;;--------------------------------------------------------------------------------------------
; _JmpCode @F,0A9h ; 花指令
; dd $ ; 这里可以放变量字符串等数据
; @@:
;;--------------------------------------------------------------------------------------------
;相当于JMP,自己改一下就可以把里面的干扰字符替换掉效果更好,呵呵 ;把x,y[地图] 字符串拆分成2个DWORD 和一个地图名字返回 _string 指向字符串 _x返回拆分转换成dword型的x _y返回拆分转换成dword型的y _map是指针存放地图名字
_cfXY proc _string,_x,_y,_map:ptr BYTE
local @Buf[100]:byte,@xBuf[10]:BYTE,@yBuf[10]:BYTE,@mBuf[13]:BYTE,@length,@addrf
pushad
invoke lstrcpy,addr @Buf,_string;拷贝数据到 @buf来计算
invoke lstrlen,addr @Buf
mov @length,eax
mov ecx,@length
mov al,','
lea edi,@Buf
repne scasb;查找,字符
jnz _Ret;没有找到相等的,结束
mov @addrf,edi
mov BYTE ptr [edi-1],0;;edi指向找到的字符下一个
invoke lstrcpy,addr @xBuf,addr @Buf;保存x
mov ecx,@length
mov edi,@addrf
mov esi,@addrf
mov al,'['
repne scasb
jnz _Ret
mov @addrf,edi
mov BYTE ptr [edi-1],0
invoke lstrcpy,addr @yBuf,esi;保存y
mov ecx,@length
mov edi,@addrf
mov esi,@addrf
mov al,']'
repne scasb
jnz _Ret
mov @addrf,edi
mov BYTE ptr [edi-1],0
invoke lstrcpy,addr @mBuf,esi;保存地图名字
invoke atodw,addr @xBuf
mov esi,_x
mov [esi],eax
invoke atodw,addr @yBuf
mov esi,_y
mov [esi],eax
invoke lstrcpy,_map,addr @mBuf;拷贝地图
_Ret:
popad
ret
_cfXY endp
;把x,y 字符串拆分成2个DWORD 供购买物品使用 _x返回拆分转换成dword型的x _y返回拆分转换成dword型的y
_cfDh proc _string,_x,_y
local @Buf[100]:byte,@xBuf[10]:BYTE,@yBuf[10]:BYTE,@mBuf[13]:BYTE,@length,@addrf
pushad
invoke lstrcpy,addr @Buf,_string;拷贝数据到 @buf来计算
invoke lstrlen,addr @Buf
mov @length,eax
mov ecx,@length
mov al,','
lea edi,@Buf
repne scasb;查找,字符
jnz _Ret;没有找到相等的,结束
mov @addrf,edi
mov BYTE ptr [edi-1],0;;edi指向找到的字符下一个
invoke lstrcpy,addr @xBuf,addr @Buf;保存x
invoke lstrcpy,addr @yBuf,@addrf;保存y
invoke atodw,addr @xBuf
mov esi,_x
mov [esi],eax
invoke atodw,addr @yBuf
mov esi,_y
mov [esi],eax
_Ret:
popad
ret
_cfDh endp
;把 名字,名字 字符串拆分成2个string返回 供地图切换使用 _Js1string _Js2string指向要接收的字符指针
_cfDT proc _string,_Js1string,_Js2string
local @Buf[100]:byte,@xBuf[10]:BYTE,@yBuf[10]:BYTE,@mBuf[13]:BYTE,@length,@addrf
pushad
invoke lstrcpy,addr @Buf,_string;拷贝数据到 @buf来计算
invoke lstrlen,addr @Buf
mov @length,eax
mov ecx,@length
mov al,','
lea edi,@Buf
repne scasb;查找,字符
jnz _Ret;没有找到相等的,结束
mov @addrf,edi
mov BYTE ptr [edi-1],0;;edi指向找到的字符下一个
invoke lstrcpy,_Js1string,addr @Buf;保存x
invoke lstrcpy,_Js2string,@addrf;保存y
_Ret:
popad
ret
_cfDT endp
;计算开根号 返回开根号后的
_sqrt proc _num
local @return
pushad
finit
mov eax,_num
test eax,eax
jnl _r2
neg eax
_r2:
mov @return,eax ;注意这种用法。可以返回整数回内存哦
fild @return ;读取整数入寄存器
fsqrt ;求开平方
fist @return ;装入整数入内存 (整数是如66这样的)
popad
mov eax,@return
ret
_sqrt endp
;计算人和怪之关的坐标位置 _ux:自己的x _uy:自己的y _gx:怪x _gy:怪y 返回计算好的
;计算方法 sqrt((x1-x2)^2 + (y1-y2)^2)
_coordinate proc _ux,_uy,_gx,_gy
local @return,@x;(x1-x2)^2
pushad
mov eax,_ux;(x1-x2)^2
sub eax,_gx
mov ecx,eax
mul ecx
mov @x,eax
mov eax,_uy;(y1-y2)^2
sub eax,_gy
mov ecx,eax
mul ecx
add @x,eax
invoke _sqrt,@x;sqrt()
mov @return,eax
popad
mov eax,@return;返回
ret
_coordinate endp ;提示功能
_ts proc _string;字符
pushad
invoke SetDlgItemText,hWin2,IDC_TS2,_string
invoke SetWindowText,hWin,_string
popad
ret
_ts endp
;模拟Qmz3 找出 人/怪/npc/传送
Qmz3 proc
push ebp
mov ebp,esp
s1:
cmp DWORD ptr [ebp+8h],0;首先测试参1是否为0
je _Ret;如果为0 结束
mov eax,[ebp+8]
cmp DWORD ptr [eax+10h],0;[A1+10]:0
je s2;为0跳
mov ecx,dword ptr [ebp+10h]
push ecx ; /Arg3
mov edx,dword ptr [ebp+0Ch] ; |
push edx ; |Arg2
mov eax,dword ptr [ebp+8h] ; |
mov ecx,dword ptr [eax+10h] ; |
push ecx ; |Arg1
call Qmz3 ; \game.0060DFE0
add esp,0Ch
s2:
mov edx,dword ptr [ebp+8h] ; edx=A1
cmp dword ptr [edx],1 ; 测试[A1]:1是否为1 如果是人/npc/传送 则一直是1
jnz s3 ; 不相等跳
mov eax,dword ptr [ebp+8h] ; 没跳走 EAX=A1
mov ecx,dword ptr [eax+24h] ; ECX=[A1+24]
and ecx,dword ptr [ebp+10h] ; [A1+24] and 4 (人/npc/怪[A1+24]一定是0eh)
je s3 ; 如果为0 就表示不是 人/怪/npc 将跳走
;最终在这里处理,没跳走就表示是 人/怪/npc了
mov edx,dword ptr [ebp+8h] ; 没跳走就表示是 人/怪/npc 的基址了
.if f_npcXs;是要取名字
;[人/怪/npc基址+1C]=当前的id [人/怪/npc基址+4]=X 计算过的 [人/怪/npc基址+8]=Y 计算过的
mov eax,[edx+1CH]
imul eax,eax,8FA0H
mov ecx,dwMzjzIdFt
add eax,[ecx]
add eax,8C08h
invoke SendDlgItemMessage,hWin3Npc,IDC_LIST1,LB_INSERTSTRING,-1,eax
.endif
.if f_QnpcId;取指定名字的npc/传送的 id 和坐标
mov eax,[edx+1CH]
imul eax,eax,8FA0H
mov ecx,dwMzjzIdFt
add eax,[ecx]
add eax,8C08h
invoke lstrcmp,addr szQnpcName,eax
.if eax==0;相等 是要查找的npc名字 则取id 和坐标
mov edx,dword ptr [ebp+8h] ;取id
mov eax,[edx+1CH]
mov dwQnpcId,eax
mov eax,[edx+4];取得坐标
mov dwGX,eax
mov eax,[edx+8]
mov dwGY,eax
mov f_QnpcId,0
.endif
.endif
s3:
mov eax,dword ptr [ebp+8h] ; eax=A1
cmp dword ptr [eax+14h],0 ; [A1+14]:0
je s4 ; 为0跳
mov ecx,dword ptr [ebp+10h]
push ecx ; /Arg3
mov edx,dword ptr [ebp+0Ch] ; |
push edx ; |Arg2
mov eax,dword ptr [ebp+8h] ; |
mov ecx,dword ptr [eax+14h] ; |
push ecx ; |Arg1
call Qmz3 ; \game.0060DFE0
add esp,0Ch
s4:
mov edx,dword ptr [ebp+8h] ; edx=A1
mov eax,dword ptr [edx+0Ch] ; EAX=[A1+C] 指向下一个结构
mov dword ptr [ebp+8h],eax ; A1=[A1+C]
jmp s1 ; 跳
_Ret:
mov esp,ebp
pop ebp
ret
Qmz3 endp
;模拟Qmz4 找出人/怪/npc/传送
Qmz4 proc
push ebp
mov ebp,esp
sub esp,8
mov dword ptr [ebp-8],ecx
mov dword ptr [ebp-4],0
jmp short KK9B
KK7B:mov eax,dword ptr [ebp-4]
add eax,1
mov dword ptr [ebp-4],eax
KK9B:cmp dword ptr [ebp-4],2
; \s3
add esp,0Ch
KKF3:jmp short KK7B
KKF5:mov esp,ebp
pop ebp
ret 8
Qmz4 endp
;遍历当前所有的人/怪/npc
_getAllRen proc
;遍历当前屏幕所有人
push 4
mov eax,dwAllRengBase
add eax,49A2Ch;数据的附加是在 屏蔽游戏场景实现优化游戏 的下层可发现的
push eax
mov ecx,dwAllRengBase
add ecx,331A8h;数据的附加是在 屏蔽游戏场景实现优化游戏 的下层可发现的
mov ecx,[ecx]
.if ecx==0;如果此数据为空 则基址+4
mov ecx,dwAllRengBase
add ecx,331A8h;数据的附加是在 屏蔽游戏场景实现优化游戏 的下层可发现的
add ecx,4
.endif
call Qmz4
ret
_getAllRen endp
;遍历仓库包包 找查找没有物品的格子并返回格子号(基于0) 如果没有则返回-1
_findCkn proc
local @return,@index,@base,@goodName[100]:BYTE,@id
pushad
mov @return,-1
mov esi,dwBagBase;仓库起始地址=[[[6CBFC0]+47C0+2D08]+3*14+c]
mov esi,[esi]
add esi,47B8H+2D08H+8H
mov esi,[esi]
add esi,3*14h+0ch
mov esi,[esi]
mov @base,esi
mov @index,1;从1开始
.while @index<41;5列8行=40个包包格子 但是仓库却多了后最后一例一直为空 也就是虚拟的仓库为6列,最后一列我们需要手动丢弃
mov eax,[esi]
.if eax==0;表示没有物品
dec @index;因为是基于0的。我们是从1开始所以要减1
mov eax,@index
; cdq
; mov ecx,5
; div ecx;总格子数除5 当前行=得到的商-1 当行列=得到的余
;
; dec ecx;当前行=得到的商-1
; mov esi,_h
; mov DWORD ptr [esi],eax;行
;
; mov esi,_l
; mov DWORD ptr [esi],edx;当行列=5-得到的余
push @index
pop @return;返回格子数
jmp _Ret
.endif
mov eax,@index;因为最第一列是空的,所以每次检测为5整除的时候就跳过第6列
cdq
mov ecx,5
div ecx
.if edx==0
add esi,4
.endif
add esi,4;前移一格
inc @index
.endw
_Ret:
popad
mov eax,@return
ret
_findCkn endp
;hook取晶石最基础基址
_hookJsJz proc
mov ebp,esp;首先执行被我们修改的hook代码
sub esp,14h
mov dword ptr [ebp-14h],ecx
pushad
pushfd
.if dwHcBase==0;第一次调用时这里为0
mov dwHcBase,ecx;保存最初玄晶基址
.endif
popfd
popad
mov eax,dwHcHookRetAddr;跳转回去
jmp eax
ret
_hookJsJz endp
;合成晶石
_hcJs proc
local @base
mov eax,dwHcBase
mov ecx,[eax+4] ;ecx=[取得基址+4]
add ecx,718h ;ecx=[取得基址+4]+718h
mov @base,ecx ;保存一下
; ;合成包包的基址=[得到的ECX+174]
; add ecx,174h
; mov esi,[ecx]
; push _id1;物品id 放入包包
; pop DWORD ptr [esi]
; push _id2
; pop DWORD ptr [esi+4]
; push _id3
; pop DWORD ptr [esi+8]
; push _id4
; pop DWORD ptr [esi+0CH]
push 0 ;1普通金币 0绑定金币
push 3
mov edx,dwHcCall
mov ecx,@base
call edx ;合成玄晶call
ret
_hcJs endp
;与npc对话
_npcDh proc _npcId;npcId
local @tick
invoke GetTickCount
mov @tick,eax
.while TRUE
push _npcId
mov ecx,8FA0h;最终是npc的ecx=1*8FA0+[6CBFBC]+50C ;6CBFBC要在第4层得到
mov esi,dwNpcBase
add ecx,[esi]
add ecx,50Ch
mov edx,dwNpcCall
call edx
;打开的npc对话框句柄=[6BE08C+8] 打开与npc对话后这里将会有数据 没打开则为0
mov esi,dwCloseNpcWBase
mov eax,[esi]
.if eax!=0
jmp _Ret
.endif
invoke Sleep,1000
invoke GetTickCount;超过了10秒还没有对上话肯定就出错了
sub eax,@tick
.if eax>6*1000
jmp _Ret
.endif
.endw
_Ret:
ret
_npcDh endp
;与仓库 邹德侩对话 与上面是一样的。但是它的区别在于 打开仓库只能点一下。不能不停的点。不然就不能保存物品了
_npcDhC proc _npcId;npcId
push _npcId
mov ecx,8FA0h;最终是npc的ecx=1*8FA0+[6CBFBC]+50C ;6CBFBC要在第4层得到
mov esi,dwNpcBase
add ecx,[esi]
add ecx,50Ch
mov edx,dwNpcCall
call edx
ret
_npcDhC endp
;点击项
_djItem proc _ItemNum;需要点击的项。基于1开始
local @ItemNum[4]:DWORD
invoke RtlZeroMemory,addr @ItemNum,sizeof @ItemNum
mov ecx,_ItemNum
imul ecx,ecx,100h
add ecx,0F8H ;;push 指针 指向一个双字数据 000001F8 其中后面的F8一直不变1代表选择第二项 项从0开始
sub ecx,100h;我们程序自己是基于1 所以这里要减100h才和程序对应
mov @ItemNum,ecx
lea esi,@ItemNum
push 0
push esi;push 指针 指向一个双字数据 000001F8 其中后面的F8一直不变1代表选择第二项 项从0开始
mov ecx,dwHcBase
mov ecx,[ecx+4]
mov edx,dwDjItemCall
call edx
ret
_djItem endp
;关闭所有打开窗口
_closeAllWindow proc
;首先关闭打开的对话窗口 (这个下面那个关闭不了)
mov ecx,dwCloseNpcWBase
mov ecx,[ecx] ;有npc对话框的时候这个数据不为0 如打开仓库 并不用对话。是直接打开仓库 所以为0
.if ecx!=0
mov eax,dwCloseWCallNk4
call eax
.endif
mov ecx,dwCloseWBase;再一次性关闭其他的杂窗口
mov edx,dwCloseWCall
call edx
invoke Sleep,1000
ret
_closeAllWindow endp
;寻路call
_walkX proc _x,_y
push 0
push _y ;y
push _x ;x
push 24h
mov ecx,dwXWalkBase
mov edx,dwXWalkCall
call edx
ret
_walkX endp
;普通走路
_walkP proc _x,_y
push 0
push _y
push _x
mov ecx,dwMzjzIdFt;ecx=1*8FA0+[6CBFBC] (这个也是"人/npc/怪的名字基址" 它再+8C08=名字
mov ecx,[ecx]
add ecx,8FA0H
mov edx,dwPWalkCall
call edx
ret
_walkP endp
;购买物品
_buy proc _wz,_num;_wz物品所在位置 _num物品数量
local @wGz
mov @wGz,30DH
push _num ;购买数量
mov eax,_wz
dec eax
push eax;(从0递增排列物品一直到最后一个)
lea esi,@wGz
push esi;push 指针 指向物品所在npc的格子id(这个无所谓是多少)
mov ecx,dwHcBase
mov ecx,[ecx+4]
add ecx,718h
mov edx,dwBuyCall
call edx
ret
_buy endp
;出售物品
_sell proc _wId,_num;物品id 出售物品数量
pushad
push _num
push _wId
mov ecx,dwHcBase
mov ecx,[ecx+4]
add ecx,718h
mov edx,dwSellCall
call edx
popad
ret
_sell endp
;保存物品
_saveGood proc _cGz,_wGz;_cGz仓库格子(基于0) _wGz包包格子(基于0)
local @l1,@l2,@l3,@l4,@l5,@l6
mov eax,_cGz
cdq
mov ecx,5
div ecx;总格子数除5 当前行=得到的商-1 当行列=得到的余
dec ecx;当前行=得到的商-1
mov @l1,eax;行
mov @l2,edx;当行列=5-得到的余
mov @l3,3;放下位置:指向3个dword [内存]=3(为2物品位置在包包 为3位置在仓库) [内存+4]物品所在列(基于0) [内存+8]=物品所在行(基于0)
mov eax,_wGz
cdq
mov ecx,5
div ecx;总格子数除5 当前行=得到的商-1 当行列=得到的余
dec ecx;当前行=得到的商-1
mov @l4,eax;行
mov @l5,edx;当行列=5-得到的余
mov @l6,2;之前位置:指向3个dword [内存]=2(为2物品位置在包包 为3位置在仓库) [内存+4]物品所在列(基于0) [内存+8]=物品所在行(基于0)
lea esi,@l3
push esi
lea esi,@l6
push esi
mov ecx,dwHcBase
mov ecx,[ecx+4]
add ecx,718h
mov edx,dwSaveGoodCall
call edx
ret
_saveGood endp
;修理物品
_trim proc _wId;物品id
push 1
push _wId
mov ecx,dwHcBase
mov ecx,[ecx+4]
add ecx,718h
mov edx,dwTrimCall
call edx
ret
_trim endp
;修理身上所有物品
_trimAll proc
local @index,@base
pushad
mov esi,dwBagBase;装备起始地址=[[[6CBFC0]+47C0+2D08]+2*14+c]
mov esi,[esi]
add esi,47B8H+2D08H+8H
mov esi,[esi]
add esi,0*14h+0ch
mov esi,[esi]
mov @base,esi
mov @index,0
.while @index<10;10个物品
mov esi,@base
mov eax,[esi]
.if eax!=0;表示有物品
invoke _trim,eax;修理
invoke Sleep,500
.endif
add @base,4;前移一格
inc @index
.endw
popad
ret
_trimAll endp
;遍历身上包包
;参数type=0 查找指定物品 将返回物品id 没找到返回0 _string有效需要指向字符
;参数type=1 查找指定物品 将返回物品所在格子 没找到返回-1 _string有效需要指向字符
;参数type=2 查找指定物品数量 返回指定的物品数量 _string有效需要指向字符
;参数type=3 遍历包包 实现出售物品 _string无效
;参数type=4 遍历包包 实现仓库保存 _string无效
;参数type=5 遍历包包 查找包包有几个物品 _string无效 想知道有几个空位就自己手动40-返回值
;参数type=6 遍历包包 查找指定的玄晶 送4个入合成框 然后合成玄晶 _string有效需要指向要合成的玄晶
_findBag proc _type,_string
local @return,@index,@base,@goodName[100]:BYTE,@id
pushad
mov @return,0
.if _type==1;查找指定物品 将返回物品所在格子 没找到返回-1
mov @return,-1
.endif
mov esi,dwBagBase;包包起始地址=[[[6CBFC0]+47C0+2D08]+2*14+c]
mov esi,[esi]
add esi,47B8H+2D08H+8H
mov esi,[esi]
add esi,2*14h+0ch
mov esi,[esi]
mov @base,esi
mov @index,0
.while @index<40;5列8行=40个包包格子
mov esi,@base
mov eax,[esi]
.if eax!=0;表示有物品
.if _type==0;参数type=0 查找指定物品 将返回物品id 没找到返回0 _string有效需要指向字符
;当前物品名字=[物品id*4F8+[A56084]+4]
mov @id,eax
mov ecx,4F8H
mul ecx
mov edi,dwGoodsNameBase
add eax,[edi]
add eax,4
mov eax,[eax]
invoke lstrcpy,addr @goodName,eax;读取物品名字
invoke lstrcmp,addr @goodName,_string
.if eax==0;找到物品退出
push @id
pop @return
jmp _Ret
.endif
.endif
.if _type==1;查找指定物品 将返回物品所在格子 没找到返回-1 _string有效需要指向字符
;当前物品名字=[物品id*4F8+[A56084]+4]
mov @id,eax
mov ecx,4F8H
mul ecx
mov edi,dwGoodsNameBase
add eax,[edi]
add eax,4
mov eax,[eax]
invoke lstrcpy,addr @goodName,eax;读取物品名字
invoke lstrcmp,addr @goodName,_string
.if eax==0;找到物品退出
push @index;返回格子
pop @return
jmp _Ret
.endif
.endif
.if _type==2;参数type=2 查找指定物品数量 返回指定的物品数量 _string有效需要指向字符
;当前物品名字=[物品id*4F8+[A56084]+4]
mov @id,eax
mov ecx,4F8H
mul ecx
mov edi,dwGoodsNameBase
add eax,[edi]
add eax,4
mov eax,[eax]
invoke lstrcpy,addr @goodName,eax;读取物品名字
invoke lstrcmp,addr @goodName,_string
.if eax==0;找到物品增加数量
inc @return
.endif
.endif
.if _type==3;出售物品
;当前物品名字=[物品id*4F8+[A56084]+4]
mov @id,eax
mov ecx,4F8H
mul ecx
mov edi,dwGoodsNameBase
add eax,[edi]
add eax,4
mov eax,[eax]
invoke lstrcpy,addr @goodName,eax;读取物品名字
invoke _SearchString,lpGoodsView,addr @goodName ;不被出售的物品
.if eax==0;
invoke _SearchString,lpGoodsView2,addr @goodName ;存入仓库的物品
.if eax==0;
invoke _sell,@id,1;出售物品
invoke Sleep,500
.endif
.endif
.endif
.if _type==4;仓库保存
;当前物品名字=[物品id*4F8+[A56084]+4]
mov @id,eax
mov ecx,4F8H
mul ecx
mov edi,dwGoodsNameBase
add eax,[edi]
add eax,4
mov eax,[eax]
invoke lstrcpy,addr @goodName,eax;读取物品名字
invoke _SearchString,lpGoodsView2,addr @goodName;存入仓库的物品
.if eax!=0;查找到就保存
invoke _findCkn;查找有空位的 基于0
.if eax!=-1;查找到才保存
invoke _saveGood,eax,@index
invoke Sleep,700
.endif
.endif
.endif
.if _type==5;参数type=5 遍历包包 查找包包有几个空位 _string无效
inc @return
.endif
.if _type==6;送4个入合成框 然后合成玄晶
;当前物品名字=[物品id*4F8+[A56084]+4]
mov @id,eax
mov ecx,4F8H
mul ecx
mov edi,dwGoodsNameBase
add eax,[edi]
add eax,4
mov eax,[eax]
invoke lstrcpy,addr @goodName,eax;读取物品名字
invoke lstrcmp,addr @goodName,_string
.if eax==0
;合成包包的基址=[得到的ECX+174]
mov eax,dwHcBase
mov ecx,[eax+4] ;ecx=[取得基址+4]
add ecx,718h ;ecx=[取得基址+4]+718h
add ecx,174h
mov esi,[ecx]
push @id;物品id 放入包包
mov eax,@return;总共需要计算4次 每次的偏移递增4
cdq
mov ecx,4
mul ecx
pop DWORD ptr [esi+eax];放入
inc @return;找到物品增加数量
.if @return>=4;放入4块就OK了。然后合成
invoke _hcJs;合成
invoke Sleep,3000
jmp _Ret
.endif
.endif
.endif
.endif
add @base,4;前移一格
inc @index
.endw
_Ret:
popad
mov eax,@return
ret
_findBag endp ;die死亡复活 call
_die proc _type;1(原地复活) 0回城疗伤
push _type
mov edx,dwDieCall
call edx
add esp,4
ret
_die endp
;测试是否死亡 死亡就根据选择方式复活
_dieFh proc
pushad
;测试是否死亡 死亡选择复活方式
mov esi,dwSxJz
mov eax,[esi]
add eax,8FA0H+308h
mov eax,[eax];当前血 血量/最大血量=[[6CD064]+id*8FA0+308]/[[6CD064]+id*8FA0+308-4]
.if eax==0
invoke IsDlgButtonChecked,hWin2,IDC_RADIO1
.if eax==BST_CHECKED;原地复活
invoke _die,1
.while TRUE;原地复活需要30秒的时间 所以期间不停的测试它的血量
mov esi,dwSxJz
mov eax,[esi]
add eax,8FA0H+308h
mov eax,[eax]
.if eax!=0;血量不为0就表示复活了
jmp @F
.endif
invoke Sleep,100
.endw
@@:
.else;回城复活
invoke _die,0
invoke Sleep,2000;
.endif
.endif
popad
ret
_dieFh endp
;右击物品
_yjwp proc _wGz;指定物品所在格子(基于)
local @l1,@l2,@l3
mov eax,_wGz
cdq
mov ecx,5
div ecx;总格子数除5 当前行=得到的商-1 当行列=得到的余
dec ecx;当前行=得到的商-1
mov @l1,eax;行
mov @l2,edx;当行列=5-得到的余
mov @l3,2;push 指向3个dword [内存]=2(为2物品位置在包包) [内存+4]物品所在列(基于0) [内存+8]=物品所在行(基于0)
lea esi,@l3
push esi
mov ecx,dwHcBase
mov ecx,[ecx+4]
add ecx,718h
mov edx,dwHjwpCall
call edx
ret
_yjwp endp ;初始化数据
_beginInit proc
;(PkClient.dll基址保存在[43BE10])
mov eax,dwPkClientB;PkClient.dll基址保存在[43BE10] [43BE10]+偏移 就是正确的数据地址
mov eax,[eax]
add dwJcMonsterEcx,eax
add dwJcMonsterCall,eax;;检测是人、怪、NPC call 在第二个参数返回8是对话npc 0A是能被攻击的npc 怪是1 人是0 灵兽是6->XX
;(Controller.dll基础=[0043B218+4])
mov eax,dwControllerB
mov eax,[eax]
add dwLeftEcx,eax
add dwLeftCall,eax;设置(人、怪、npc)为选择中状态
add dwLeft2Call1,eax
add dwAllMonsterBase,eax;(基址)=[[6FB2A60]+25C]+4+20 开始遍历所有怪
add dwIsMonsterEcx,eax
add dwIsMonsterCall,eax;这里取出数据为 1则是人 2是npc/怪
add dwSelf8438,eax;[[6F52A60]+288] 这个就得到了当前自己的 [基址+8438] ->XX
add dwCmpSelfMEcx,eax
add dwCmpSelfMCall,eax;比较人和怪之间的距离 返回距离数值 ->XX
add dwYingXMn1,eax;*这几个*的代码是程序硬性要求规定的,我们也需要把它模拟进去
add dwYingXEcx1,eax;*这几个*的代码是程序硬性要求规定的,我们也需要把它模拟进去
add dwYingXCall1,eax;*这几个*的代码是程序硬性要求规定的,我们也需要把它模拟进去
add dwYingXEcx2,eax;*这几个*的代码是程序硬性要求规定的,我们也需要把它模拟进去
add dwYingXCall2,eax;*这几个*的代码是程序硬性要求规定的,我们也需要把它模拟进去
;(ThingClient.dll基础=[43DA68])
mov eax,dwThingClientB
mov eax,[eax]
;add dwIsMonsterNpc,eax;[[基址+8438]]=545746CH 才是怪/npc
ret
_beginInit endp
_changeM proc
ret
_changeM endp
;选择怪物 没有怪物返回0 有怪返回基址
_changeMonster proc
local @return,@saveBase,@num,@returnData,@save8438,@selfXy,@monsterXy
pushad
mov @return,0
lea edi,@selfXy
push edi
mov ecx,dwSelf8438
mov ecx,[ecx]
mov ecx,[ecx+288h];[[6F52A60]+288] 这个就得到了当前自己的 [基址+8438] ->XX
mov edx,dwSelf8438
mov edx,[edx]
mov edx,[edx+288h]
mov edx,[edx]
call DWORD ptr [edx+14h];在参1返回坐标 返回eax=参1 (在参1中返回的是双字 高16位是y 低16位是x)
mov eax,dwAllMonsterBase
mov eax,[eax]
mov eax,[eax+25ch]
add eax,4;[ebp-10]=[[6FB2A60]+25C]+4
mov edx,[eax]
mov ecx,eax
call DWORD ptr [edx+14h];返回 eax=[[6FB2A60]+25C]+4+20 (这个一定要模拟 这个里面会重组所有怪物列表)
mov @saveBase,eax;(基址)=[[6FB2A60]+25C]+4+20 开始遍历所有怪
mov @num,0
.while TRUE
mov ecx,@saveBase
mov eax,[ecx+4]
mov ebx,[ecx]
sub eax,ebx
sar eax,2;返回([0043B144+4]-[0043B144])/4 应该是当前怪物数量
cmp @num,eax
jnb _Ret;不低于。也就是大于等于就要跳。因为遍历过了所有怪了
mov eax,@num
lea eax,[eax*4]
mov ebx,@saveBase
add eax,[ebx]
mov eax,[eax];[[ecx(0043B144)]+参1*4] 这里得到的是[基址+8438]
mov @save8438,eax
mov eax,@save8438
mov edx,[eax]
mov ecx,@save8438
call DWORD ptr [edx+8];eax=[[ebp-24]+8] edx=[[ebp-24]+c]
push edx
push eax
mov ecx,dwIsMonsterEcx
mov edx,dwIsMonsterCall
call edx;这里取出数据为 1则是人 2是npc/怪
.if eax==2
xor ecx,ecx;*这几个*的代码是程序硬性要求规定的,我们也需要把它模拟进去
mov ecx,dwYingXMn1
mov cl,[ecx]
and ecx,1
.if ecx==0
mov edx,dwYingXMn1
mov eax,edx
mov dl,[edx]
or dl,1
mov BYTE ptr [eax],dl
mov ecx,dwYingXEcx1
mov edx,dwYingXCall1
call edx
mov ecx,dwYingXEcx2
push ecx
mov edx,dwYingXCall2
call edx
add esp,4
.endif;*这几个*的代码是程序硬性要求规定的,我们也需要把它模拟进去
lea edi,@returnData
push edi
push @save8438
mov ecx,dwJcMonsterEcx
mov ecx,[ecx]
mov edx,dwJcMonsterCall
call edx;检测是人、怪、NPC 在第二个参数返回8是对话npc 0A是能被攻击的npc 怪是1 人是0 灵兽是6->XX
.if @returnData==1 ;|| @returnData==8
lea edi,@monsterXy
push edi
mov ecx,@save8438
mov edx,@save8438
mov edx,[edx]
call DWORD ptr [edx+14h];在参1返回坐标 返回eax=参1 (在参1中返回的是双字 高16位是y 低16位是x)
mov eax,@monsterXy
mov ebx,eax
shr eax,16;
push eax;push 怪y
and ebx,0ffffh
push ebx;push 怪x
mov eax,@selfXy
mov ebx,eax
shr eax,16
push eax;push 自己x
and ebx,0FFFFH
push ebx;push 自己y
mov ecx,dwCmpSelfMEcx
mov edx,dwCmpSelfMCall
call edx;;比较人和怪之间的距离 返回距离数值 ->XX
.if eax<12
mov ecx,@save8438;[真正的基址+8438]+10=当前的名字
add ecx,10h
mov ebx,@save8438;血量=[[基址+8438]+34]
add ebx,34h
mov eax,[ebx];
invoke wsprintf,addr szScript,$str('%s=%d'),ecx,eax
invoke SendDlgItemMessage,hWin2,IDC_LIST1,LB_INSERTSTRING,-1,addr szScript
invoke SendDlgItemMessage,hWin2,IDC_LIST1,LB_SETCURSEL,eax,NULL
push @save8438
pop @return
jmp _Ret
.endif
.endif
.endif
inc @num;每次增长1
.endw
_Ret:
popad
mov eax,@return
ret
_changeMonster endp
;按键
_keyPress proc _key,_bykey
push _bykey
push _key
mov ecx,dwKeyPressEcx
mov edx,dwKeyPressCall
call edx
ret
_keyPress endp
;右击选中怪/npc
_leftPress proc _jz8438
pushad
push _jz8438
mov ecx,dwLeftEcx
mov ecx,[ecx]
mov edx,dwLeftCall;选中怪/npc ->XX (下面也有一个选中怪/npc的功能,但是参数是要基址,而我们这遍历怪物返回的是[基址+8438] 所以得用此处的功能)
call edx
popad
ret
_leftPress endp
;右击一下 是怪就是普通打 是npc就是对话
_leftPressD proc _jz
local @data1,@data2,@data3,@data4
pushad
lea ecx,@data4
mov edx,06F6A920h
call edx ;这里面使[ebp-48]=6F974A0 [ebp-48+4]=0 [ebp-48+8]=0 [ebp-48+C]=0
mov ecx,dwLeftEcx
mov ecx,[ecx]
mov ecx,[ecx+62ch];ecx= 在上3层得到[43B218] 在上1层又计算了 [[43B218]+62C]
add ecx,8
push ecx;push [[43B218]+62C]+8
push _jz;push 基址
lea ecx,@data4
mov edx,dwLeft2Call1
call edx;这里面使[ebp-48+4]=基址 [ebp-48+8]=[基址+8438] [ebp-48+C]=参1
.if eax
mov eax,_jz
mov eax,[eax+8438h];ecx=[基址+8438] (此处数据+10h也是 人、怪、NPC的名字)
.if eax
lea esi,@data4
push esi
mov ecx,eax
mov edx,eax
mov edx,[edx]
call DWORD ptr [edx+50h];右击(人、怪、npc) 怪就是普通攻击 npc就是对话 ->XX
.endif
.endif
popad
ret
_leftPressD endp
;攻击指定怪物
_hitMonster proc _jz8438;怪物[基址+8438]
local @tick,@xue
mov eax,_jz8438
add eax,34h
mov eax,[eax];血量=[[基址+8438]+34]
.if eax;血量不为0才进入
invoke GetTickCount
mov @tick,eax
invoke _leftPress,_jz8438;右击选中怪/npc
.while TRUE
invoke _keyPress,'1',20001h;按1键
mov eax,_jz8438
add eax,34h;血量=[[基址+8438]+34]
mov eax,[eax]
.if eax==0
jmp _Ret;血量为0退出
.endif
invoke GetTickCount
sub eax,@tick
.if eax>12*1000;超过10秒退出
jmp _Ret
.endif
invoke Sleep,1200
.endw
.endif
_Ret:
ret
_hitMonster endp
;自动战斗
_hit proc _type
invoke SetDlgItemText,hWin,IDOK,$str('停止挂机')
mov f_play,1;播放标识
.while f_play
invoke _changeMonster;查找怪物
.if eax
invoke _hitMonster,eax;攻击指定怪物
.endif
invoke Sleep,500
.endw
invoke GetDlgItem,hWin,IDOK
invoke EnableWindow,eax,TRUE
invoke SetDlgItemText,hWin,IDOK,$str('开始挂机')
ret
_hit endp
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
上传的附件: