七夜式作者——萌新
本文详细介绍了七夜式的研究开发过程
本文所有代码遵循GPLv2许可证发布
https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
※以下内容皆为转载
s溢出的注意点:
1.每隔1kb的代码必须要有一个00,否则mugen会直接在相应位置插入00,导致代码错误
2.不能出现00,3B
3.st文件不要放在第一个,会导致异常
Statedef状态号溢出攻击研究
# 检测研究
## 基础知识
Statedef溢出原理:压入的状态号过长将esp中原本的返回位置覆盖了
47EBF0是文件处理入口,47F18A,47ECF1,47F23F是返回到溢出写入地址的位置
47E9B6也是一个返回地址
4949F0 改动4B2188处可以在对方的读取线程里插入自己的代码,这个地方的原始值是49221E
注入时获取的esp与对方的状态号返回地址差值10D0 注入时不可读 1p人物信息指针尚未赋值
esp-DD0出是对方正在处理的文件名字符串头
状态号返回地址对应堆栈位置的值不固定,进入到溢出区段时可能是正常的地址,在区段中地址保持不变,之后那个位置的值基本随机
状态号与获取的esp的差值:0D21FF54-0D21EE4C=1108,这个位置是状态号的空格
esp-dd0处不是00时尚未开始读取statedef状态号
使用常规的检测太慢,需要一些手段
考虑在对方的状态号返回地址处设置硬件断点,在写入时触发,触发之后会调用异常处理函数。把事先写好的异常处理函数加入对方读取线程的SEH链中。硬件断点会抛出EXCEPTION_SINGLE_STEP异常
进入异常处理函数之后,如果是EXCEPTION_SINGLE_STEP异常就说明对方正在写入状态号返回地址,检查是否正在读取statedef,如果是则判断返回地址是否是正常值
如果返回地址不是正常值,就改成47EB31
返回
在使用中断+断点之后就不必再设置开始检查和结束检查的条件,只要等到对方的人物信息基地址不是00就进入下一步即可。在这个过程中子线程不执行任何动作。
statedef溢出检查完全在对方的线程里执行,子线程不干预
fs:[0]指向的区域是可读的,不用担心
由于硬件断点的限制,需要在47EBF0处再设置一个硬件断点,在47EBF0处的异常处理函数里启用对47F18A的断点,在47F18A处的异常处理函数里启用对47EBF0的断点
## 初步思路:
### 对方子线程:
构造一个新的EXCEPTION_REGISTRATION结构,函数地址是statedef_of_dectet_pre,prev是fs:[0]。
修改对方线程的fs:[0],即SEH链,指向上一步构造的结构
在edi+40处设置一个硬件断点,在写入时触发
### 异常处理函数:
取出EXCEPTION_RECORD,读出其中的ExceptionCode和ExceptionAddress
检查ExceptionCode是否是EXCEPTION_SINGLE_STEP(0x80000004),不是返回EXCEPTION_CONTINUE_SEARCH (0)
检查[esp]是否是47EB31或者47E9B6,不是改成47EB31并且4B42F0改成1,返回EXCEPTION_CONTINUE_EXECUTION
异常处理函数入口地址[4B4300]
~~# 详细设计:~~
~~## 对方子线程:~~
~~1. 保存esp到4B4120~~
~~2. push 异常处理函数入口地址,push fs:[0],构造新的SEH链结构~~
~~3. mov fs:[0],esp,装入~~
~~4. 写入“GetCurrentThread”~~
~~5. 获取GetCurrentThread的地址,保存~~
~~1. 写入“SuspendThread”~~
~~1. 获取SuspendThread的地址,保存~~
~~2. 写入“ResumeThread"~~
~~1. 获取ResumeThread的地址,保存~~
~~6. 写入“GetThreadContext”~~
~~1. 获取GetThreadContext的地址,保存~~
~~8. 写入“SetThreadContext”~~
~~1. 获取SetThreadContext的地址,保存~~
~~10. 调用GetCurrentThread,获取当前线程的句柄,保存到内存中~~
~~1. 在[4B4200]写入FFFFFFFF~~
~~1. 调用SuspendThread,暂停自己~~
~~## 己方子线程:~~
~~1. 检查[4B4200]是否是FFFFFFFF,不是继续检查~~
~~11. 调用GetThreadContext,获取对方子线程的Context~~
~~11. 读dr6,判断异常原因~~
~~12. 如果是47F18A引发异常 修改Context,Dr0写入47EBF0,Dr7写入401,其他部分不改动;否则修改Context,Dr1写入47F18A,Dr7写入404~~
~~14. 调用SetThreadContext,写入新的Context~~
~~14. 在[4B4200]写入10101010~~
~~15. 调用ResumeThread,恢复对方子线程~~
如果在47F18A处设置一个断点,然后在异常处理函数里把CONTEXT->EIP改成403249,重新启用dr0,即让程序从另一个ret指令处返回,避开硬件断点,并返回EXCEPTION_CONTINUE_EXECUTION让程序从403249开始执行
## 原理:
Intel 提供了Drx寄存器用于设置硬件断点,执行到硬件断点处会产生单步异常。
在对方的47F18A处设置硬件断点并注入对方选人线程的SEH,在对方执行到47F18A时会触发单步异常。这时自己定义的异常处理函数会被调用,通过判断此时选人线程的返回地址来判断对方是否使用了statedef溢出,如果是就修正地址并通知自己的子线程,之后修改eip到另一个ret指令处,重新启用断点并通知系统忽略异常,这样选人线程会继续执行。当对方读取完毕时自己的子线程进入下一功能模块。
47F18A处只在处理状态定义时执行,执行时返回地址必然是状态定义处理的返回地址,稳定可靠
## 详细设计:
### 对方子线程:
1. 保存esp到4B4120
1. push 异常处理函数入口地址,push fs:[0],构造新的SEH链结构
1. mov fs:[0],esp,装入
1. 写入“GetCurrentThread”
1. 获取GetCurrentThread的地址,保存
1. 写入“SuspendThread”
1. 获取SuspendThread的地址,保存
1. 写入“ResumeThread"
1. 获取ResumeThread的地址,保存
1. 写入“GetThreadContext”
1. 获取GetThreadContext的地址,保存
1. 写入“SetThreadContext”
1. 获取SetThreadContext的地址,保存
1. 调用GetCurrentThread,获取当前线程的伪句柄,保存到内存中
1. 调用GetCurrentProcess获取当前进程的伪句柄(49F0E8)
1. 调用DuplicateHandle获取当前进程的真实句柄,参数为CurrentProcess,CurrentThread,CurrentProcess,4BE320,00000000,01,00000002
1. 在[4B4200]写入FFFFFFFF
1. 调用SuspendThread,暂停自己
### 己方子线程:
1. 检查[4B4200]是否是FFFFFFFF,不是继续检查
1. 调用GetThreadContext,获取对方子线程的Context
1. 修改Context,Dr0写入47F18A,Dr1写入47ECF1,Dr2写入47F23F,Dr7写入415
1. 调用SetThreadContext,写入新的Context
1. 在[4B4200]写入00000000
1. 调用ResumeThread,恢复对方子线程
### 异常处理函数:
push ebp
mov ebp,esp
sub esp,08
push ebx
push esi
push edi
mov eax,[ebp+08];第一个参数ExceptionRecord的地址
mov eax,[eax];第一个参数ExceptionRecord的ExceptionCode
cmp [eax],0x80000004;是否是EXCEPTION_SINGLE_STEP异常
jne 交给其他的处理函数
mov eax,[4B4120]
sub eax,10D0
cmp [eax],47EB31
je 返回
cmp [eax],47E9B6
je 返回
mov [eax],47EB31
mov [4B42F0],1
mov eax,FFFFFFFF
jmp 返回
交给其他的处理函数:
xor eax,eax
返回:
修改CONTEXT->DR7为401
修改CONTEXT->EIP为403249
pop edi
pop esi
pop ebx
mov esp,ebp
pop ebp
ret
## 编码:
### 对方子线程:
### 异常处理函数:
push ebp
mov ebp,esp
sub esp,08
push ebx
push esi
push edi
mov eax,[ebp+08];第一个参数ExceptionRecord的地址
mov eax,[eax];第一个参数ExceptionRecord的ExceptionCode
cmp [eax],0x80000004;是否是EXCEPTION_SINGLE_STEP异常
jne 交给其他的处理函数
mov eax,[4B4120]
sub eax,10D0
cmp [eax],47EB31
je 返回
cmp [eax],47E9B6
je 返回
mov [eax],47EB31
mov [4B42F0],1
mov eax,FFFFFFFF
jmp 返回
交给其他的处理函数:
xor eax,eax
返回:
mov [4B4200],FFFFFFFF
调用SuspendThread,暂停自己
pop edi
pop esi
pop ebx
mov esp,ebp
pop ebp
ret
except_handler:
push ebp
mov ebp,esp
sub esp,08
push ebx
push esi
push edi
mov eax,[ebp+08];第一个参数ExceptionRecord的地址
mov eax,[eax];第一个参数ExceptionRecord的ExceptionCode
cmp [eax],0x80000004;是否是EXCEPTION_SINGLE_STEP异常
jne ret_search
mov eax,[4B4120]
sub eax,10D0
cmp [eax],47EB31
je ret_EXECUTION
cmp [eax],47E9B6
je ret_EXECUTION
mov [eax],47EB31
mov [4B42F0],1
mov eax,FFFFFFFF
jmp ret_EXECUTION
ret_search:
xor eax,eax
ret_EXECUTION:
;修改CONTEXT->DR7为401
;获取CONTEXT的指针
mov edx,[ebp+10]
mov edx,[edx]
add edx,18
mov [edx],401
;修改CONTEXT->EIP为403249
add edx,A0
mov [edx],403249
pop edi
pop esi
pop ebx
mov esp,ebp
pop ebp
ret
# 编码:
对方子线程:
pushad
pushfd
mov [4B4120],esp
push 4B3000
push fs:[0]
mov fs:[0],esp
;写入“GetCurrentThread”,从4BE200开始,避开1p的字符串
mov [4BE200],43746547
mov [4BE204],65727275
mov [4BE208],6854746E
mov [4BE20C],72656164
push 49F604;KERNEL32
call dword ptr [49F0B8];KERNEL32.GetModuleHandleA,获取KERNEL32.dll地址
mov edi,eax
push 4BE200
push edi
call dword ptr [49F130]
mov [4BE300],eax
;写入“SuspendThread”
mov [4BE200],70737553
mov [4BE204],54646E65
mov [4BE208],61657268
mov [4BE20C],00000064
push 4BE200
push edi
call dword ptr [49F130]
mov [4BE304],eax
;写入“ResumeThread"
mov [4BE200],75736552
mov [4BE204],6854656D
mov [4BE208],64616572
mov [4BE20C],00000000
push 4BE200
push edi
call dword ptr [49F130]
mov [4BE308],eax
;写入“GetThreadContext”
mov [4BE200],54746547
mov [4BE204],61657268
mov [4BE208],6E6F4364
mov [4BE20C],74786574
push 4BE200
push edi
call dword ptr [49F130]
mov [4BE310],eax
;写入“SetThreadContext”
mov [4BE200],54746553
mov [4BE204],61657268
mov [4BE208],6E6F4364
mov [4BE20C],74786574
push 4BE200
push edi
call dword ptr [49F130]
mov [4BE314],eax
;写入“DuplicateHandle”
mov [4BE200],6C707544
mov [4BE204],74616369
mov [4BE208],6E614865
mov [4BE20C],00656C64
push 4BE200
push edi
call dword ptr [49F130]
mov [4BE318],eax
;调用GetCurrentThread,获取当前线程的句柄,保存到[4BE320]
call dword ptr [4BE300]
mov [4BE320],eax
;调用GetCurrentProcess获取当前进程的伪句柄(49F0E8)
call dowrd ptr [49F0E8]
;调用DuplicateHandle获取当前进程的真实句柄,参数为CurrentProcess,CurrentThread,CurrentProcess,4BE320,00000000,01,00000002
push 00000002
push byte 01
push 00000000
push 4BE320
push eax
push [4BE320]
push eax
call dword ptr [4BE318]
mov [4B42F0],FFFFFFFF
;调用SuspendThread,暂停自己
push [4BE320]
call dword ptr [4BE304]
popfd
popad
ret
己方子线程:
set_breakpoint:
cmp [4B42F0],FFFFFFFF
jne set_breakpoint_pre
;调用GetThreadContext,获取对方子线程的Context,写入到4B4300
push 4B4300
push [4BE320]
call dword ptr [4BE310]
;修改Context,Dr0写入47F18A,Dr7写入401
mov [4B4304],47F18A
mov [4B4318],401
;调用SetThreadContext,写入新的Context
push 4B4300
push [4BE320]
call dword ptr [4BE314]
;恢复标志位
mov [4B42F0],01010101
;调用ResumeThread,恢复对方子线程
push [4BE320]
call dowrd ptr [4BE308]
Dr7为00000000000000000000010000000001,设置是:启用Dr0,局部;关闭保护;写入时触发;断点长度4字节。注意大小端的问题。
00000000000000000000010000000100
需要注意的点:
线程退出时这些内存区域会变成不可读,如果判断的条件不对会造成报错,即使条件是对的,如果由于多线程问题也有可能出现报错。 利用VirtualQurey检查是否可读
如果能够确定mugen对于各个文件的读取顺序,那么发现对应位置不再是“Statedef”时退出检测 x 对于多个st文件的人物会出现检测失败的情况。
如果能够有判断st文件已经全部完成读取的方法,那么就可以实现稳定检测了 x 可能不需要了
检查读取出的内存开头+4是否是“eate”这个方法是否可靠,会不会出现满足条件但是并不是在处理statdef状态号或者不满足条件但是是在处理statedef状态号的情况
在触发断点之后会取消断点的有效位,所以要在异常处理函数中暂停对方子线程并通过一个内存中的标志通知自己的子线程重新写入标志位。 x 利用异常处理函数获取的线程上下文直接恢复断点并设置eip避开断点
在应用层是不能直接操作Drx寄存器的值,但可以调用这两个api来读写线程的上下文,来达到设置硬件断点的目的,
不要使用EXCEPTION_EXECUTE_HANDLER,返回的地址是不明确的
把写入异常处理函数和对方子线程的工作放到statedef文件里进行,不需要给1p写额外的分支,对方选人进程suspend已经足够了,子线程的1p侧攻击也不需要改
使用GetThreadContext需要先构造一个CONTEXT结构体并初始化其中的Context.ContextFlags,Context.ContextFlags设置为CONTEXT_FULL。具体方式在4B4300那里写入一个3F
GetCurrentThread返回的线程永远指向当前线程
异常处理函数的值必须是以下其一
typedef enum _EXCEPTION_DISPOSITION {
ExceptionContinueExecution,
ExceptionContinueSearch,
ExceptionNestedException,
ExceptionCollidedUnwind
} EXCEPTION_DISPOSITION;
ExceptionContinueExecution 表示:已经处理了异常,回到异常触发点继续执行。
ExceptionContinueSearch 表示:没有处理异常,继续遍历异常链表。
ExceptionCollidedUnwind 表示在展开过程中再次触发异常。
EXCEPTION_RECORD struct{ //共6个成员
+0 DWORD ExceptionCode //异常代码,定义了产生异常的原因
+4 DWORD ExceptionFlags //异常标志 ?
+8 struct EXCEPTION_RECORD //指针,指向另一个EXCEPTION_RECORD结构
+C DVOID ExceptionAddress //异常发生的地址
+10 DWORD NumberParameters //与异常联系的参数个数(0~15)一般=0 ?
+14 ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS] //异常信息 ?
}EXCEPTION_RECORD ends
typedef struct _CONTEXT {
/*000*/ DWORD ContextFlags;
/*004*/ DWORD Dr0;
/*008*/ DWORD Dr1;
/*00C*/ DWORD Dr2;
/*010*/ DWORD Dr3;
/*014*/ DWORD Dr6;
/*018*/ DWORD Dr7;
/*01C*/ FLOATING_SAVE_AREA FloatSave;
/*08C*/ DWORD SegGs;
/*090*/ DWORD SegFs;
/*094*/ DWORD SegEs;
/*098*/ DWORD SegDs;
/*09C*/ DWORD Edi;
/*0A0*/ DWORD Esi;
/*0A4*/ DWORD Ebx;
/*0A8*/ DWORD Edx;
/*0AC*/ DWORD Ecx;
/*0B0*/ DWORD Eax;
/*0B4*/ DWORD Ebp;
/*0B8*/ DWORD Eip;
/*0BC*/ DWORD SegCs;
/*0C0*/ DWORD EFlags;
/*0C4*/ DWORD Esp;
/*0C8*/ DWORD SegSs;
/*0CC*/ BYTE ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];
/*2CC*/ } CONTEXT;
EXCEPTION_DISPOSITION __cdecl _except_handler (
_In_ struct _EXCEPTION_RECORD *_ExceptionRecord, //异常记录结构指针
_In_ void * _EstablisherFrame, //指向EXCEPTION_REGISTRATION结构,即SEH链
_Inout_ struct _CONTEXT *_ContextRecord, //Context结构指针 (线程上下文)
_Inout_ void * _DispatcherContext //无意义 (调度器上下文?)
);
# 对于state缺失型溢出的处理思考
对于state缺失型溢出而言,上述处理方法依然能够检测出溢出,但是由于溢出的statedef无控制器不合法,不能完成读取。这时按照普通方法处理mugen会不停地读取这个statedef,溢出会多次执行,并且无法开局。
目前的做法是检测到这种溢出直接关闭程序,不过也可做如下设想:在对方的statedef溢出后面加上一个null控制器,这样对方就有了一个控制器的_文本_,如果重新读取时能够读取到,那个就能解除无限读取并且开幕。
根据新的拉莱耶文本,ebx是控制mugen是否重新加载statedef的控制器,修改它的值就可以阻止mugen重新读取statedef
那么改为在读取statedef处设置硬件断点,检查读入的statedef号长度,超过56的部分去除,同时覆盖ebx阻止重新读取statedef,就可以拦截所有的s溢出
x
47EBF0处的esp指向返回地址,只要返回地址不是标准值就可以认为发生了S溢出
;==========================
%n与textbug研究
思路:利用s溢出写入暂停代码和断点设置与SEH注入代码。之后通过主线程调用的代码来让主线程执行暂停。线程检测到主线程暂停之后设置断点与SEH函数,之后恢复主线程执行
重点:
1. 给出判断%n与textbug的方式
2. 找出速度最快的主线程调用代码
已知:
1.4967DF是%n和%d的处理函数,ecx为写入的原始字符串(%n等没有替换为实际数值),,edx是最后完成替换的字符串,ebx是参数,%n位于496CB6处,ecx为写入的值
2.4ABDC4处的字符串“trigger%i"可以修改并且可以调用%f,但是这个调用不是在主线程里进行的
3.edx是“%n”出现的地方
4.4969BA处下断点,[eax]是字符串长度,textbug的长度似乎是0x403
5.%d的返回值是定值4713F3
6.%i同样会出现textbug
7.edx是字符串读写指针,指向当前要写入的字符位置。在[eax]达到0x403时,指向返回地址的第二个字节
8.text的参数可以为空
9.text会被缓存,第一次之后的写入都是读取缓存写入。缓存中“%n”的字符串如果改成“%d”,那么以后这个text所有的“%n”都会被%d取代。edi指向缓存当前正在读取的字符
10.主线程被暂停后fs:[0]指向的SEH可能会被释放,需要找到入口地址是496150的seh节点并且覆盖
11.由于硬件断点的限制,在4967DF下断点会导致4967DF出的push无法执行,这样会导致堆栈错误。必须自己完成断点语句的动作。4967EE处的xor esi,esi指令动作容易完成并且寄存器变动不大,可以在此处设置断点.4969BA的add esp,0C很容易模拟
12.od在seh的检测上面效果很差,可以使用CE在异常处理处下断点来查看运行情况
13.触发%n检测之后textbug会导致主程序十分卡顿
研究:
1.%n只需要检查字符串中是否有“%n”即可,textbug需要计算字符串长度,其中%xxxd的计算是一个问题
2.既然极限卢使用修改按键处理的方法执行自己的代码并且能够在其他人物选择前执行指向改,那么也许这个方法速度是足够的
3.改掉正常的mugen提示,强行加入%f
4.使用GetWindowThreadProcessId获取窗口线程ID,如果是主线程创建窗口即可获得
5.用CreateToolhelp32Snapshot获取所线程的快照
通过GetWindowThreadProcessId找出mugen的pid。
在进程里找出mugen之后,逐个获取线程id,用OpenThread打开获取句柄,通过GetThreadTimes检测线程的用户时间,用CompareFileTime比较,最长的就是主线程
6.fs:[30]+3000处似乎是主线程的TEB,+24处是主线程id。该处内存可读,之后通过openthread打开即可获得句柄
7.在4967DF处设置断点检查“%n”,在4969BA处下断点检查[eax]是否等于0x403
8.cns指空对已经读取的控制器有何影响?对未读取的控制器有何影响?
9.是否可以修改textbug的地址直接使textbug跳过汇编代码直接返回?
10.是否可以修改edi和edx指向的两个字符串的头部分,将原本的代码改为textbug的返回代码?
11.修改字符串时不能清除掉原有的%d之类字符,因为它们与dtc的params紧密相关,缺少一个都会导致栈异常
结论:
2. x 按键处理不在主线程执行
4. x 主线程没有创建窗口
5. x 谁会写谁写
6.可行
8.未知,但是使用cns指空之后%n检测触发后卡顿的问题得到了解决
9.x
10.可行
11.不完全正确,%d可以没有参数,但是有些不行
;==========================
※汇编代码部分
alloc(newmem,2048)
label(palno_range)
label(start)
label(palno_detect)
label(sff)
label(attack_init)
label(defense)
label(p1_attack_init)
label(p2_attack_init)
label(p2_is_selected)
label(attack)
label(enemy_displayname)
label(mugen_path)
label(cmd_select)
label(p2_cmd)
label(attack_fin)
label(p1)
label(p3)
label(p3_leitaizhan)
label(p5)
label(p7)
label(p2)
label(p4)
label(p4_leitaizhan)
label(p6)
label(p8)
label(set_breakpoint)
label(p1_pre_in_round_fix)
label(p1_defense)
label(p1_in_round_init)
label(p1_in_round_detecte)
label(p1_in_round_fix)
label(p1_player_button_off_fix)
label(p2_defense)
label(p2_pre_in_round_detecte)
label(p2_pre_in_round_fix)
label(p2_in_round_init)
label(p2_in_round_detecte)
label(p2_in_round_fix)
label(p2_player_button_off_fix)
label(exit)
label(next_round_dectet)
4BE010:
start:
pushad
pushfd
mov esi,[4B41A0]
mov edi,[4B41A4]
mov [4B4194],454C10
mov eax,[4B6178]
mov [4B40A0],eax
;这段是傻瓜包的一部分
;根据之前获取的栈地址去判断p侧
palno_detect:
cmp [esi-000047A4],edi
je p1
cmp [esi-00004790],edi
je p3
cmp [esi-00004748],edi
je p3_leitaizhan
cmp [esi-000046EC],edi
je p5
cmp [esi-00004690],edi
je p7
cmp [esi-00002D08],edi
je p2
cmp [esi-00002CF4],edi
je p4
cmp [esi-00002CAC],edi
je p4_leitaizhan
cmp [esi-00002C50],edi
je p6
cmp [esi-00002BF4],edi
je p8
jmp palno_detect
p1:
mov eax,[esi-000047A0]
mov [4B42FF],FFFFFFFF
jmp palno_range
p3:
mov eax,[esi-0000478C]
mov [4B42FF],FFFFFFFF
jmp palno_range
p3_leitaizhan:
mov eax,[esi-00004744]
mov [4B42FF],FFFFFFFF
jmp palno_range
p5:
mov eax,[esi-000046E8]
mov [4B42FF],FFFFFFFF
jmp palno_range
p7:
mov eax,[esi-0000468C]
mov [4B42FF],FFFFFFFF
jmp palno_range
p2:
mov eax,[esi-00002D04]
mov [4B42FF],11111111
jmp palno_range
p4:
mov eax,[esi-00002CF0]
mov [4B42FF],11111111
jmp palno_range
;某个特殊模式的player4
p4_leitaizhan:
mov eax,[esi-00002CA8]
mov [4B42FF],11111111
jmp palno_range
p6:
mov eax,[esi-00002C4C]
mov [4B42FF],11111111
jmp palno_range
p8:
mov eax,[esi-00002BF0]
mov [4B42FF],11111111
jmp palno_range
;判断p数,选择头像
palno_range:
cmp eax,01
ja palno_detect
cmp eax,00
jb palno_detect
mov [4B4270],eax
mov ebp,eax
mov ebx,eax
cmp [ebp*4+4B41E0],00000000
jne sff
mov edx,[4B42A0]
add ebx,66732E40
mov [4B42D6],ebx
push 4BDFF0
push edx
call [4B4194]
add esp,08
mov [ebp*4+4B41E0],eax
;换头像
sff:
mov ecx,[4B41AF]
mov edx,[ebp*4+4B41E0]
mov [ecx],edx
;判断之前保存下来的自己的p数
mov eax,[4B4270]
;1p,进入攻击模块
cmp eax,00
je attack_init
;否则进入防御模块
jmp defense
attack_init:
;攻击用的cmd命令
mov [4B4000],72616863
mov [4B4004],616E5C73
mov [4B4008],6179616E
mov [4B400C],6968735F
mov [4B4010],695C696B
mov [4B4014],78742E31
mov [4B4018],00000074
mov [4B401C],72616863
mov [4B4020],616E5C73
mov [4B4024],6179616E
mov [4B4028],6968735F
mov [4B402C],695C696B
mov [4B4030],78742E32
mov [4B4034],00000074
mov [4B4038],72616863
mov [4B403C],616E5C73
mov [4B4040],6179616E
mov [4B4044],6968735F
mov [4B4048],695C696B
mov [4B404C],65642E33
mov [4B4050],00000066
mov [4B4054],61657243
mov [4B4058],69466574
mov [4B405C],41656C
mov [4B4060],64616552
mov [4B4064],656C6946
mov [4B4068],00000000
mov [4B406C],74697257
mov [4B4070],6C694665
mov [4B4074],00000065
mov [4B4090],736F6C43
mov [4B4094],6E614865
mov [4B4098],00656C64
mov [4B40F0],456E6957
mov [4B40F4],00636578
;获取CreateFile,ReadFile,WriteFile和CloseHandle的地址
push 49F604
call dword ptr [49F0B8]
mov edi,eax
push 4B4054
push edi
call dword ptr [49F130]
mov [4B4100],eax
push 4B4060
push edi
call dword ptr [49F130]
mov [4B4104],eax
push 4B406C
push edi
call dword ptr [49F130]
mov [4B4108],eax
push 4B4090
push edi
call dword ptr [49F130]
mov [4B411C],eax
push 4B40F0
push edi
call dword ptr [49F130]
mov [4B41F0],eax
mov ebp,[4B5B4C]
;判断之前保存的p侧数据
;1p侧
cmp [4B42FF],FFFFFFFF
je p1_attack_init
;2p侧
cmp [4B42FF],11111111
je p2_attack_init
jmp start
p1_attack_init:
;判断p2是否已选
p2_is_selected:
mov eax,[ebp+00000FCC]
;没有选择,在这里等待
cmp eax,-01
;已经选择
je p2_is_selected
;求出p2的displayname基地址
mov eax,[ebp+00000F80]
mov ebx,[ebp+00000FCC]
imul eax,ebx
add eax,[ebp+00000FEC]
jmp attack
p2_attack_init:
mov eax,[ebp+00000F80]
mov ebx,[ebp+00000FBC]
imul eax,ebx
add eax,[ebp+00000FDC]
attack:
mov edx,438
imul eax,edx
mov ecx,[4B54C8]
add ecx,04
add ecx,eax
mov [4B4400],ecx
xor ebx,ebx
;获取敌人的displayname并写入到重启用的def文件中
enemy_displayname:
inc ebx
cmp [ecx+ebx],00000000
mov eax,[ecx+ebx-1]
mov [ebx+4B301D],eax
jne enemy_displayname
mov [4B4405],ebx
push 00
push 00000080
push 03
push 00
push 00
push 80000000
push 4B4000
call dword ptr [4B4100]
mov [4B4120],eax
push 00
push 4B4406
push 1E
push 4B3000
push [4B4120]
call dword ptr [4B4104]
push [4B4120]
call dword ptr [4B411C]
mov [ebx+4B301E],00000022
mov [ebx+4B301F],0000000D
mov [ebx+4B3020],0000000A
push 00
push 00000080
push 03
push 00
push 00
push 80000000
push 4B401C
call dword ptr [4B4100]
mov [4B4124],eax
mov eax,4B3021
add eax,ebx
push 00
push 4B4406
push 000003C6
push eax
push [4B4124]
call dword ptr [4B4104]
push [4B4124]
call dword ptr [4B411C]
push 00
push 00000080
push 02
push 00
push 00
push 40000000
push 4B4038
call dword ptr [4B4100]
mov [4B4128],eax
mov eax,000003E6
add eax,ebx
push 00
push 4B4406
push eax
push 4B3000
push [4B4128]
call dword ptr [4B4108]
push [4B4128]
call dword ptr [4B411C]
call dword ptr [49F0B0]
mov [4B412C],eax
mov [4B4200],20646D63
mov [4B4204],5420632F
mov [4B4208],4B4B5341
mov [4B420C],204C4C49
mov [4B4210],2F20462F
mov [4B4214],22204946
mov [4B4218],444E4957
mov [4B421C],4954574F
mov [4B4220],20454C54
mov [4B4224],4D207165
mov [4B4228],472E552E
mov [4B422C],4E2E452E
mov [4B4230],22262622
xor ebx,ebx
;获取mugen主程序的绝对路径
mugen_path:
inc ebx
mov dl,[eax+ebx]
cmp dl,22
je cmd_select
mov [ebx+4B4233],dl
jmp mugen_path
;写入后续重启cmd命令
cmp [4B42FF],FFFFFFFF
jne p2_cmd
mov eax,4B4233
mov [eax+ebx],20202022
mov [eax+ebx+04],2031702D
mov [eax+ebx+08],616E616E
mov [eax+ebx+0C],735F6179
mov [eax+ebx+10],696B6968
mov [eax+ebx+14],6F79725C
mov [eax+ebx+18],5F696775
mov [eax+ebx+1C],6B696873
mov [eax+ebx+20],65642E69
mov [eax+ebx+24],702D2066
mov [eax+ebx+28],616E2032
mov [eax+ebx+2C],6179616E
mov [eax+ebx+30],6968735F
mov [eax+ebx+34],695C696B
mov [eax+ebx+38],65642E33
mov [eax+ebx+3C],722D2066
mov [eax+ebx+40],646E756F
mov [eax+ebx+44],26322073
mov [eax+ebx+48],6C656426
mov [eax+ebx+4C],61686320
mov [eax+ebx+50],6E5C7372
mov [eax+ebx+54],79616E61
mov [eax+ebx+58],68735F61
mov [eax+ebx+5C],5C696B69
mov [eax+ebx+60],642E3369
mov [eax+ebx+64],00006665
jmp attack_fin
p2_cmd:
mov eax,4B4233
mov [eax+ebx],20202022
mov [eax+ebx+04],2031702D
mov [eax+ebx+08],616E616E
mov [eax+ebx+0C],735F6179
mov [eax+ebx+10],696B6968
mov [eax+ebx+14],2E33695C
mov [eax+ebx+18],20666564
mov [eax+ebx+1C],2032702D
mov [eax+ebx+20],616E616E
mov [eax+ebx+24],735F6179
mov [eax+ebx+28],696B6968
mov [eax+ebx+2C],6F79725C
mov [eax+ebx+30],5F696775
mov [eax+ebx+34],6B696873
mov [eax+ebx+38],65642E69
mov [eax+ebx+3C],722D2066
mov [eax+ebx+40],646E756F
mov [eax+ebx+44],26322073
mov [eax+ebx+48],6C656426
mov [eax+ebx+4C],61686320
mov [eax+ebx+50],6E5C7372
mov [eax+ebx+54],79616E61
mov [eax+ebx+58],68735F61
mov [eax+ebx+5C],5C696B69
mov [eax+ebx+60],642E3369
mov [eax+ebx+64],00006665
attack_fin:
push 00
push 4B4200
call dword ptr [4B41F0]
;防御模块
defense:
mov ebp,[4B5B4C]
cmp [ebp+0000FEC],FFFFFFFF
je defense
cmp [4B42FF],FFFFFFFF
je p1_defense
cmp [4B42FF],11111111
je p2_defense
jmp defense
p1_defense:
mov ecx,[4B41A4]
inc ecx
mov ebx,[ebp+CD0]
sub ebx,A1E
mov edx,E30
imul ecx,edx
add ecx,ebx
mov [4B4400],ecx
mov edx,313E313E
add edx,30303030
cmp [ecx],edx
jne p1_pre_in_round_fix
mov edx,432F3149
add edx,30303030
cmp [ecx+04],edx
jne p1_pre_in_round_fix
mov edx,393B3938
add edx,30303030
cmp [ecx+08],edx
jne p1_pre_in_round_fix
mov edx,3030305F
sub edx,30303030
cmp [ecx+0C],edx
jne p1_pre_in_round_fix
mov edx,313E313E
add edx,30303030
cmp [ecx-206],edx
jne p1_pre_in_round_fix
mov edx,432F3149
add edx,30303030
cmp [ecx-202],edx
jne p1_pre_in_round_fix
mov edx,393B3938
add edx,30303030
cmp [ecx-1FE],edx
jne p1_pre_in_round_fix
mov edx,363533FE
add edx,30303030
cmp [ecx-1FA],edx
jne p1_pre_in_round_fix
set_breakpoint:
cmp [4B42F0],FFFFFFFF
jne set_breakpoint
mov [4B4300],3F
push 4B4300
push [4BE320]
call dword ptr [4BE310]
mov [4B4304],47F18A
mov [4B4308],47ECF1
mov [4B430C],47F23F
mov [4B4318],415
push 4B4300
push [4BE320]
call dword ptr [4BE314]
mov [4B42F0],01010101
push [4BE320]
call dword ptr [4BE308]
jmp p1_in_round_init
p1_pre_in_round_fix:
mov [4B42F0],1
p1_in_round_init:
cmp dword ptr [ebp+0000B758],00
je p1_in_round_init
mov [4B2188],49221E
mov eax,[4B5B4C]
mov ebp,eax
add ebp,0000B754
mov ebp,[ebp]
mov edi,eax
add edi,0000B758
mov edi,[edi]
mov edx,[ebp+00000BE8]
mov esi,[edx]
mov [4B4200],esi
p1_in_round_detecte:
mov ecx,[eax+B654]
add ecx,30
mov esi,[edx]
cmp [4B4200],esi
jne p1_in_round_fix
cmp [4B69B8],01
je p1_in_round_fix
cmp [4B6A38],01
je p1_in_round_fix
cmp [ebp+00000158],00
je p1_in_round_fix
cmp dword ptr [edi+00002620],00
jne p1_in_round_fix
cmp [4B48E8],496651
jne p1_in_round_fix
cmp dword ptr [4B42F0],00
jne p1_in_round_fix
mov ebx,313E313E
add ebx,30303030
cmp [ecx],ebx
jne p1_in_round_fix
mov ebx,432F3149
add ebx,30303030
cmp [ecx+4],ebx
jne p1_in_round_fix
mov ebx,393B3938
add ebx,30303030
cmp [ecx+8],ebx
jne p1_in_round_fix
cmp [4B5960],429CB0
jne p1_in_round_fix
cmp [4B48E8],496651
jne p1_in_round_fix
cmp [4B48EC],4962FB
jne p1_in_round_fix
cmp [4B48F0],496361
jne p1_in_round_fix
cmp [4B48F4],4962A1
jne p1_in_round_fix
mov ebx,[4B6178]
cmp [4B40A0],ebx
jne p1_in_round_fix
cmp dword ptr [ebp],00
je exit
jmp p1_in_round_detecte
p1_in_round_fix:
mov esi,[4B4200]
mov [edx],esi
mov [ebp+00000E24],00000001
mov esi,[edi+00000BE8]
mov [esi],4B4290
mov [edi+00000E24],00000000
mov [4B48E8],496651
mov ebx,313E313E
add ebx,30303030
mov [ecx],ebx
mov ebx,432F3149
add ebx,30303030
mov [ecx+4],ebx
mov ebx,393B3938
add ebx,30303030
mov [ecx+8],ebx
mov ebx,[4B40A0]
mov [4B6178],ebx
cmp dword ptr [ebp],00
je exit
cmp [ebp+158],01
je p1_in_round_fix
cmp [4B69B8],1
je p1_player_button_off_fix
cmp [4B6A38],1
je p1_player_button_off_fix
mov [ebp+158],01
jmp p1_in_round_fix
p1_player_button_off_fix:
mov [4B5948],0
mov [4B594C],1
mov [4B699D],1
mov [4B69B8],1
mov [4B5548],2
jmp p1_in_round_fix
p2_defense:
mov ecx,[4B41A4]
inc ecx
mov ebx,[ebp+CD0]
sub ebx,A1E
mov edx,E30
imul ecx,edx
add ecx,ebx
mov [4B4400],ecx
p2_pre_in_round_detecte:
mov edx,313E313E
add edx,30303030
cmp [ecx],edx
jne p2_pre_in_round_fix
mov edx,432F3149
add edx,30303030
cmp [ecx+04],edx
jne p2_pre_in_round_fix
mov edx,393B3938
add edx,30303030
cmp [ecx+08],edx
jne p2_pre_in_round_fix
mov edx,3030305F
sub edx,30303030
cmp [ecx+0C],edx
jne p2_pre_in_round_fix
mov edx,313E313E
add edx,30303030
cmp [ecx-206],edx
jne p2_pre_in_round_fix
mov edx,432F3149
add edx,30303030
cmp [ecx-202],edx
jne p2_pre_in_round_fix
mov edx,393B3938
add edx,30303030
cmp [ecx-1FE],edx
jne p2_pre_in_round_fix
mov edx,363533FE
add edx,30303030
cmp [ecx-1FA],edx
jne p2_pre_in_round_fix
cmp [4B5960],429CB0
jne p2_pre_in_round_fix
cmp [4B48E8],496651
jne p2_pre_in_round_fix
cmp [4B48EC],4962FB
jne p2_pre_in_round_fix
cmp [4B48F0],496361
jne p2_pre_in_round_fix
cmp [4B48F4],4962A1
jne p2_pre_in_round_fix
cmp dword ptr [ebp+0000B758],00
jne p2_in_round_init
jmp p2_pre_in_round_detecte
p2_pre_in_round_fix:
mov [4B42F0],01
mov [4B5960],429CB0
mov [4B48E8],496651
mov [4B48EC],4962FB
mov [4B48F0],496361
mov [4B48F4],4962A1
mov edx,[4B4130]
mov [4B6178],edx
p2_in_round_init:
mov eax,[4B5B4C]
mov ebp,eax
add ebp,0000B758
mov ebp,[ebp]
test ebp,ebp
jz p2_in_round_init
mov edi,eax
add edi,0000B754
mov edi,[edi]
mov edx,[ebp+00000BE8]
mov esi,[edx]
mov [4B4200],esi
p2_in_round_detecte:
mov ecx,[eax+B658]
add ecx,30
mov esi,[edx]
cmp [4B4200],esi
jne p2_in_round_fix
cmp [4B69B8],01
je p2_in_round_fix
cmp [4B6A38],01
je p2_in_round_fix
cmp dword ptr [edi+00002620],00
jne p2_in_round_fix
cmp [4B48E8],496651
jne p2_in_round_fix
cmp dword ptr [4B42F0],00
jne p2_in_round_fix
mov ebx,313E313E
add ebx,30303030
cmp [ecx],ebx
jne p2_in_round_fix
mov ebx,432F3149
add ebx,30303030
cmp [ecx+4],ebx
jne p2_in_round_fix
mov ebx,393B3938
add ebx,30303030
cmp [ecx+8],ebx
jne p2_in_round_fix
cmp [4B5960],429CB0
jne p2_in_round_fix
cmp [4B48E8],496651
jne p2_in_round_fix
cmp [4B48EC],4962FB
jne p2_in_round_fix
cmp [4B48F0],496361
jne p2_in_round_fix
cmp [4B48F4],4962A1
jne p2_in_round_fix
mov ebx,[4B6178]
cmp [4B40A0],ebx
jne p2_in_round_fix
cmp dword ptr [edi],00
je exit
cmp dword ptr [ebp+0000BC30],01
jne p2_in_round_detecte
jmp p2_in_round_detecte
p2_in_round_fix:
mov esi,[4B4200]
mov [edx],esi
mov [ebp+00000E24],00000001
mov esi,[edi+00000BE8]
mov [esi],4B4290
mov [edi+00000E24],00000000
mov [4B48E8],496651
mov ebx,313E313E
add ebx,30303030
mov [ecx],ebx
mov ebx,432F3149
add ebx,30303030
mov [ecx+4],ebx
mov ebx,393B3938
add ebx,30303030
mov [ecx+8],ebx
mov ebx,[4B40A0]
mov [4B6178],ebx
cmp dword ptr [edi],00
je exit
cmp [4B69B8],1
je p2_player_button_off_fix
cmp [4B6A38],1
je p2_player_button_off_fix
jmp p2_in_round_fix
p2_player_button_off_fix:
mov [4B5948],0
mov [4B594C],1
mov [4B699D],1
mov [4B69B8],1
mov [4B5548],3
jmp p2_in_round_fix
exit:
mov eax,[4B5B4C]
add eax,FBC
mov [eax],FFFFFFFF
next_round_dectet:
cmp [eax],FFFFFFFF
je next_round_dectet
mov [eax+10],FFFFFFFF
popfd
popad
jmp esi