能力值:
( LV2,RANK:10 )
|
-
-
2 楼
我来纠正一下,楼主这种解释是歪解了: "原因是产生异常后系统调用了nt!KiTrap03( )时令eip - 1" 无论是LONG INT3 还是 INT3指令,触发后系统是绝对不会修改EIP的, 其实所有的异常触发之后,系统都不会修改EIP,这个是原则问题, 就是保留现场的意思.而将EIP减去1的这个操作,是调试器做的, 这样解释,刚好也符合了你后面所说的:LONG INT3在触发后,EIP停留在异常位置+1的地方,为什么会这样傻? 其实这个是OD的BUG,OD作者开发的时候,应该是没有考虑到LONG INT3的处理,一切触发INT3的异常,就无脑将EIP-1, 所以出现了楼主所说的情况,(INT3无脑-1=异常位置),而(LONG INT3无脑-1 = 异常位置+1) 如果不是无脑-1的话,那么触发LONG INT3应该是-2,而EIP应该是停留在ExceptionAddress处. OD笑话不少,人品差的人怎么可能做得出好的软件.
|
能力值:
( LV3,RANK:21 )
|
-
-
3 楼
flarejune
我来纠正一下,楼主这种解释是歪解了:
"原因是产生异常后系统调用了nt!KiTrap03( )时令eip - 1"
无论是LONG INT3 还是 INT3指令,触发后系统是绝 ... .text:00436CEF loc_436CEF: .text:00436CEF ; _KiTrap03+D6j .text:00436CEF mov esi, ecx .text:00436CF1 mov edi, edx .text:00436CF3 mov edx, eax .text:00436CF5 mov ebx, [ebp+68h] .text:00436CF8 dec ebx ; eip-1 .text:00436CF9 mov ecx, .text:00436CFE mov eax, 80000003h ; 异常类型 .text:00436D03 call CommonDispatchException ; 处理异常
这是KiTrap03的部分代码,确实是使eip - 1。您说的那个原则问题,可能是你只认为中断机制就是保留现场,恢复现场。 但是int3指令本来就使0x86cpu用来支持调试的一条指令,他确实比较特殊。 如果您有什么问题可以用windbg自己去查看一下KiTrap03函数的汇编代码。 多谢回复。
最后于 2020-6-7 17:21
被码小芹编辑
,原因:
|
能力值:
( LV2,RANK:10 )
|
-
-
4 楼
看你EIP前EIP后的,估计可能还是个XP系统,好吧,其它我姑且不理,以上这个图,是在WIN10下运行的,这个是我在调试"调试器"时候的截图,触发INT3异常时候,IP是790,而不是78F. 你上面说的减一,我是打死不相信微软这样做的,如果这样做的话,微软可以去死了.真的. 如果你还不服气,你自己跑一个DEMO吧,不是IP不变的话,你回来通知我吃屎好吧. static LONG CALLBACK VectoredHandler(
_In_ PEXCEPTION_POINTERS ExceptionInfo
)
{
if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT)
{
//Increase EIP/RIP to continue execution.
#ifdef _WIN64
ExceptionInfo->ContextRecord->Rip++;
#else
ExceptionInfo->ContextRecord->Eip++;
#endif
return EXCEPTION_CONTINUE_EXECUTION;
}
return EXCEPTION_CONTINUE_SEARCH;
}
void Interrupt_3()
{
PVOID Handle = AddVectoredExceptionHandler(1, VectoredHandler);
__debugbreak();
RemoveVectoredExceptionHandler(Handle);
} 你调用Interrupt_3函数,在自定义异常处理里面,++是跳过这个INT3指令,如果按你所说的话,那么不应该是++跳过,而是+=2跳过.你思维还跟不上的话,我懒得和你扯了.
最后于 2020-6-7 17:56
被flarejune编辑
,原因: 修正错别字
|
能力值:
( LV3,RANK:21 )
|
-
-
5 楼
。
最后于 2020-6-7 18:21
被码小芹编辑
,原因:
|
能力值:
( LV2,RANK:10 )
|
-
-
6 楼
码小芹
。
你不是献丑,你是误人子弟罢了. 减一操作是不是调试器做的,你看不了OD的代码,你可以看下X64DBG TITANENGINE的代码: https://github.com/x64dbg/TitanEngine/blob/51ba022c29d3faae424ac6c51c0d7fb0a4cb5b84/TitanEngine/TitanEngine.Debugger.DebugLoop.cpp#L472 你只是静态看了这个汇编指令,你都没有跑过,你怎么知道系统有执行过那段指令? 实践出真理,不要死读书诗,尽信书不如无书.
|
能力值:
( LV3,RANK:21 )
|
-
-
7 楼
flarejune
你不是献丑,你是误人子弟罢了.
减一操作是不是调试器做的,你看不了OD的代码,你可以看下X64DBG TITANENGINE的代码:
https://github.com/x64dbg/Titan ...
多谢大师的教诲
|
能力值:
( LV3,RANK:20 )
|
-
-
8 楼
学到了,大佬厉害厉害
|
能力值:
( LV2,RANK:10 )
|
-
-
9 楼
系统不会减1,减1需要调试器自行处理。int3 和int 3都会使指令实际位置在eip+1(被替换得那个指令位置+1).硬件执行断点可以准确得断在eip位置,不需要调试器修正eip
|
能力值:
( LV3,RANK:21 )
|
-
-
10 楼
zylyy
系统不会减1,减1需要调试器自行处理。int3 和int 3都会使指令实际位置在eip+1(被替换得那个指令位置+1).硬件执行断点可以准确得断在eip位置,不需要调试器修正eip
哥呀,你再仔细读读我写的文章
|
能力值:
( LV2,RANK:10 )
|
-
-
11 楼
看雪已经沦为52POJIE之类的FW场所了, 通过修改文章来掩饰自己的错误,然后反驳别人说别人诬陷它. 和之前某人做假图的方式一样,废物为了面子,啥都做了. **************************
最后于 2020-6-8 22:20
被kanxue编辑
,原因: 就事论事,以理服人!请注意语气,勿让他人感到不适
|
能力值:
( LV2,RANK:10 )
|
-
-
12 楼
"所以当cpu执行到此断点时就会执行0xCC(即INT3指令),接着产生异常去执行函数nt!KiTrap03(%20),此函数会将指令指针(eip)的值减一,因为其刚执行完0xCC此时eip指向0xCC的下一个字节,所以减一后eip重新指向0xCC(断点处)。接着会调用nt!KiDisPatchException( )函数并将异常分发给调试器" 这个是原话,关键点:触发INT(0XCC)后,nt!KiTrap先将EIP减一,再调用KiDisPatchException( )函数将异常分发给调试器. 到后面就改文章解释为:"此异常是第二次分发异常的时候使eip-1",其实傻屌依然是犯错,因为一旦触发异常,如果调试器不接手的话,直接抛出到SEH,SEH不接手就直接程序崩溃了,有它妹的第一第二次....再而且,如果将EIP-1的话,调试器不处理而直接NTContinune的话,那么就会无限循环了,一直卡在这个INT3这里, 而原文中后面对LONG INT3异常为什么依然EIP-1而不是EIP-2的描述,已经偷偷删除,因为那个是解释不过去了. 幸亏你小学的时候不是文科代表,要不然还真的中你道道了,玩文字游戏么?
|
能力值:
( LV3,RANK:21 )
|
-
-
13 楼
flarejune
"所以当cpu执行到此断点时就会执行0xCC(即INT3指令),接着产生异常去执行函数nt!KiTrap03(%20),此函数会将指令指针(eip)的值减一,因为其刚执行完0xCC此时eip ...
你看,急眼了急眼了
|
能力值:
( LV2,RANK:10 )
|
-
-
14 楼
高深的东西你是肯定不懂的了,我来告诉你nt!KiTrap里面那个减一是什么东西吧. nt!KiTrap里面减一的那个并非是"真正的EIP",真正的EIP是在TEB里面的,nt!KiTrap修改的那个是准备传递给SEH或者VEH的参数 PEXCEPTION_POINTERS -> ExceptionRecord->Eip的值,如果有设置SEH处理或者VEH处理的话,比如我3楼那个例子, 那么在这里访问到的PEXCEPTION_POINTERS -> ExceptionRecord->Eip的值,就是真实Eip-1的值.你可以查看PEXCEPTION_POINTERS->ExceptionRecord的结构,数下Eip这个成员所在的偏移是不是0x68,也就是你所说的: .text:00436CF5 mov ebx, [ebp+68h] .text:00436CF8 dec ebx ; eip-1 到现在为止,你该死而瞑目了吧. 好了,还要说一句:别叫我大佬,叫我伯伯,我做大佬的时候你还在穿开裆裤,你现在还叫我大佬?
|
能力值:
( LV3,RANK:21 )
|
-
-
15 楼
flarejune
高深的东西你是肯定不懂的了,我来告诉你nt!KiTrap里面那个减一是什么东西吧.
nt!KiTrap里面减一的那个并非是"真正的EIP",真正的EIP是在TEB里面的,nt!K ...
我现在是真心请教你,我们本来就是新手。 你上来就那种语气,我是真的受不了。 我就是请教你一下,那个od忽略异常的意思不就是异常交给程序和系统处理吗,那为什么程序没有处理,但是其eip却依然减一了呢 ?(我的意思也是此时调试器也没有处理啊) 我这是真心请教你,你能不能好好说话。当然要觉得我这种新手不配进入这个圈那就算了,耽误你时间了。
|
能力值:
( LV4,RANK:50 )
|
-
-
16 楼
不要吵了以我为准 系统减 1 (0xcc) 的操作在 KiDispatchException 头部 if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) 系统int3执行流程是 中断硬件程序 -> KiDebugTrapOrFault(r0) -> KiExceptionDispatch(r0) -> KiDispatchException(r0)->r3
|
能力值:
( LV2,RANK:10 )
|
-
-
17 楼
码小芹
我现在是真心请教你,我们本来就是新手。
你上来就那种语气,我是真的受不了。
我就是请教你一下,那个od忽略异常的意思不就是异常交给程序和系统处理吗,那为什么程序没有处理,但是其eip却依然减一了呢 ...
我不是这个圈那个圈的,我也很少来看雪,不过我注册看雪的帐号好像也有些年份了吧, 首先来说,我不是做逆向的,我是一个23年开发经验的开发者,我的逆向知识,也是前几年才随便看看的. 最近在开发调试器和做反反调试处理,所以去各大论坛看下收集下民意,如果有历史记录可以看的话, 你应该也就是发现我最近才活跃. 我说话语气就是那样的,我就是你们口中所说的那种少年得志的人,所以从小到大我都是那种语气说话. 回答你上面的问题, 正常来说,调试器是将非自己设置的INT3才当作是"异常",而忽略异常不处理的话,这里的异常就肯定是指那些非调试器自己设定的INT3. 那么问题来了,为什么时候会触发非调试器自己的INT3呢?莫非就是2个,1.程序跑飞了,2.被调试的程序自己做的int3(通常是反调试才会这样做). 而你说的那个情况,应该是第2条,正如我上面说的,触发异常后,系统调用SEH/VEH询问该如何处理,如果程序自身有做了SEH/VEH的话,就会在异常处理 函数里面对异常进行处理,而在调用SEH/VEH的时候,其参数PEXCEPTION_POINTERS->ExceptionRecord->Eip已经被减少1,用户处理完异常后, 必须会调用NTCONTINUE继续执行程序,那么系统就会将参数里面的Context写会到真实的ThreadContext里面去,所以,你什么都不做的话,其实经过这番操作后,EIP其实已经是减1了. 话又反过来说,就是因为刻意操作才会有INT3的产生,所以按实际情况的话,在VEH/SEH里面,用户是必定会对EIP进行处理的,就好像我4楼那个例子一样. 如果用户不处理的话,就会出现死循环,程序立马卡死无响应.
|
能力值:
( LV3,RANK:21 )
|
-
-
18 楼
flarejune
我不是这个圈那个圈的,我也很少来看雪,不过我注册看雪的帐号好像也有些年份了吧,
首先来说,我不是做逆向的,我是一个23年开发经验的开发者,我的逆向知识,也是前几年才随便看看的.
最近在开发调试器和 ...
谢谢你的回复,我自己去写个简单的调试器验证一下。
|
能力值:
( LV3,RANK:21 )
|
-
-
19 楼
#include <Windows.h>
#include <iostream>
using namespace std;
int flag = 0; //标志
int main()
{
char a[256] = {0};
cout<<"请输入需要调试的目标程序的路径:";
cin>>a;
PROCESS_INFORMATION pi; //接受新进程的一些有关信息
STARTUPINFO si; //指定新进程的主窗体如何显示
DEBUG_EVENT devent; //消息事件
CONTEXT stContext; //线程信息块
GetStartupInfo(&si);
CreateProcessA(
a,
NULL,
NULL,
NULL,
FALSE, // 不可继承
DEBUG_ONLY_THIS_PROCESS | DEBUG_PROCESS, // 调试模式启动 (DEBUG_ONLY_THIS_PROCESS标志表示其不能调试进程如果被调试的话,此新进程不会成为其调试进程的调试对象)
NULL,
NULL,
&si,
&pi );
cout<<"创建进程成功"<<endl;
while(TRUE)
{
if(WaitForDebugEvent(&devent, INFINITE))
{
switch(devent.dwDebugEventCode)
{
case EXCEPTION_DEBUG_EVENT:
switch(devent.u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_BREAKPOINT: //断点异常
if(devent.u.Exception.dwFirstChance == 1) //第一次异常分发
{
cout<<"第一次异常。 ";
cout<<"eip:";
stContext.ContextFlags = CONTEXT_FULL;
GetThreadContext(pi.hThread, &stContext);
int n1 = GetLastError();
cout<<stContext.Eip<<endl;
flag = 1;
}
if(devent.u.Exception.dwFirstChance == 0) //第二次异常分发
{
cout<<"第二次异常。 ";
cout<<"eip:";
GetThreadContext(pi.hThread, &stContext);
cout<<stContext.Eip<<endl;
flag = 0;
}
break;
}
break;
}
}
if(flag == 1) //如果是第一次碰见int3断点异常,我们不处理他,让他直接继续进行第二次异常分发
ContinueDebugEvent(devent.dwProcessId, devent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
else //如果是第二次碰见int3断点异常或者是其他调试事件我们直接返回让程序继续运行
{
flag = 0;
ContinueDebugEvent(devent.dwProcessId, devent.dwThreadId, DBG_CONTINUE);
}
}
return 0;
}
就此结束把,我要去准备期末考试了。 要不就得挂科了
|
能力值:
( LV2,RANK:10 )
|
-
-
20 楼
码小芹
#include <Windows.h>
#include <iostream>
using&n ... 你这不是变着花样****?现在的年轻人,就是喜欢被***是吧? 我来和你说,你这个被调试的CmdLine1.exe的代码里面,是加了SEH或者VEH的, 你这个程序的执行过程如下:
执行遇到INT3指令->系统进入异常分发处理->检测有调试器否,有则直接提交给调试器(此时真实EIP没变)->现有调试器进行处理,如果调试器 ContinueDebugEvent(DBG_EXCEPTION_NOT_HANDLED)->系统准备SEH/VEH处理分发->将准备的参数PEXCEPTION_POINTERS -> ExceptionRecord->Eip减一后调用到SEH/VEH处理函数 ->SEH/VEH处理函数处理完毕->调用NTContinue继续执行->NtContinue里将PEXCEPTION_POINTERS -> ExceptionRecord写回到线程上下文(这里注意里,由于刚才调用SEH/VEH函数 之前,已经将PEXCEPTION_POINTERS -> ExceptionRecord->Eip减了1,此时直接写回去的话,真实的EIP就变成了异常地址-1)->程序继续执行,但是由于当前EIP下面的还是那个INT3断点, 所以再次触发异常->系统再次进入处理者分发处理环节(Exception.dwFirstChance从1变为0,也就是你说的第二次...)
以上说的这个和我17楼说的内容一致.你的解释也没有为你说清楚系统修改了EIP这个情况.而实际上,系统根本没有修改过你的EIP(你还看不懂这句的话,你仔细琢磨下,关键问题是在那个NtContinue里面). 如果你那个CmdLine1.exe没有加入SEH/VEH处理的话,你在第一次异常调用ContinueDebugEvent(DBG_EXCEPTION_NOT_HANDLED)后,程序是直接崩溃了的,没有后文的了. 我不知道你是真傻还是假傻,将这个细节的东西隐藏了,然后发半个测试结果上来.和做假图的那些人没区别,人品差到极致,建议别继续学下去了,侮辱业界.
PS:题外话,你以上这个调试器的代码逻辑有问题,你那个PI的变量是你主线程,而你在调试器处理环节里面,你应该使用devent.dwThreadId来获取当前异常的线程,而不是抓住主线程来X. 而由于你测试的程序刚好是单线程的,所以你这样搞也没有发现问题.
最后于 2020-6-8 22:18
被kanxue编辑
,原因: 就事论事,以理服人!请注意语气,勿让他人感到不适
|
能力值:
( LV3,RANK:21 )
|
-
-
21 楼
flarejune
你这不是变着花样找脸抽么?现在的年轻人,就是喜欢被抽脸是吧?
我来和你说,你这个被调试的CmdLine1.exe的代码里面,是加了SEH或者VEH的,
你这个程序的执行过程如下:
执行遇 ...
哈哈哈,这个cmdline1.exe还真没有seh/veh
|
能力值:
( LV3,RANK:21 )
|
-
-
22 楼
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Sample code for < Win32ASM Programming 3rd Edition> ; by 罗云彬, http://www.win32asm.com.cn ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; CmdLine.asm ; 命令行参数的获取和分析例子 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 使用 nmake 或下列命令进行编译和链接: ; ml /c /coff Cmdline.asm ; Link /subsystem:windows Cmdline.obj ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> .386 .model flat,stdcall option casemap:none ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Include 文件定义 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> include windows.inc include user32.inc includelib user32.lib include kernel32.inc includelib kernel32.lib ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 数据段 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> .data? szBuffer1 db 4096 dup (?) szBuffer2 db 4096 dup (?) szOutput db 8192 dup (?)
.const szCaption db '命令行参数',0 szFormat1 db '可执行文件名称:',0dh,0ah,'%s',0dh,0ah,0ah db '参数总数:%d',0dh,0ah,0 szFormat2 db '参数[%d]:%s',0dh,0ah,0 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 代码段 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> .code include _Cmdline.asm ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> start: invoke GetModuleFileName,NULL,offset szBuffer1,sizeof szBuffer1 invoke _argc mov ebx,eax invoke wsprintf,addr szOutput,addr szFormat1,addr szBuffer1,eax
xor esi,esi .while esi < ebx invoke _argv,esi,addr szBuffer2,sizeof szBuffer2 invoke wsprintf,addr szBuffer1,addr szFormat2,esi,addr szBuffer2 invoke lstrcat,addr szOutput,addr szBuffer1 inc esi .endw invoke MessageBox,NULL,addr szOutput,addr szCaption,MB_OK invoke ExitProcess,NULL ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> end start
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Sample code for < Win32ASM Programming 3rd Edition> ; by 罗云彬, http://www.win32asm.com.cn ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; _CmdLine.asm ; 命令行参数分析的通用子程序 ; 功能: ; _argc ---> 对命令行参数进行数量统计 ; _argv ---> 取某个命令行参数 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; ; ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> CHAR_BLANK equ 20h ;定义空格 CHAR_DELI equ '"' ;定义分隔符 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 取命令行参数个数 (arg count) ; 参数个数必定大于等于 1, 参数 1 为当前执行文件名 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> _argc proc local @dwArgc
pushad mov @dwArgc,0 invoke GetCommandLine mov esi,eax cld _argc_loop: ;******************************************************************** ; 忽略参数之间的空格 ;******************************************************************** lodsb or al,al jz _argc_end cmp al,CHAR_BLANK jz _argc_loop ;******************************************************************** ; 一个参数开始 ;******************************************************************** dec esi inc @dwArgc _argc_loop1: lodsb or al,al jz _argc_end cmp al,CHAR_BLANK jz _argc_loop ;参数结束 cmp al,CHAR_DELI jnz _argc_loop1 ;继续处理参数内容 ;******************************************************************** ; 如果一个参数中的一部分有空格,则用 " " 包括 ;******************************************************************** @@: lodsb or al,al jz _argc_end cmp al,CHAR_DELI jnz @B jmp _argc_loop1 _argc_end: popad mov eax,@dwArgc ret
_argc endp ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 取指定位置的命令行参数 ; argv 0 = 执行文件名 ; argv 1 = 参数1 ... ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> _argv proc _dwArgv,_lpReturn,_dwSize local @dwArgv,@dwFlag
pushad inc _dwArgv mov @dwArgv,0 mov edi,_lpReturn
invoke GetCommandLine mov esi,eax cld _argv_loop: ;******************************************************************** ; 忽略参数之间的空格 ;******************************************************************** lodsb or al,al jz _argv_end cmp al,CHAR_BLANK jz _argv_loop ;******************************************************************** ; 一个参数开始 ; 如果和要求的参数符合,则开始复制到返回缓冲区 ;******************************************************************** dec esi inc @dwArgv mov @dwFlag,FALSE mov eax,_dwArgv cmp eax,@dwArgv jnz @F mov @dwFlag,TRUE @@: _argv_loop1: lodsb or al,al jz _argv_end cmp al,CHAR_BLANK jz _argv_loop ;参数结束 cmp al,CHAR_DELI jz _argv_loop2 cmp _dwSize,1 jle @F cmp @dwFlag,TRUE jne @F stosb dec _dwSize @@: jmp _argv_loop1 ;继续处理参数内容
_argv_loop2: lodsb or al,al jz _argv_end cmp al,CHAR_DELI jz _argv_loop1 cmp _dwSize,1 jle @F cmp @dwFlag,TRUE jne @F stosb dec _dwSize @@: jmp _argv_loop2 _argv_end: xor al,al stosb popad ret
_argv endp ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
这是cmdline1的源代码,我只是把其exe程序的第二条指令改为int3,来测试观点
|
能力值:
( LV2,RANK:10 )
|
-
-
23 楼
还来****?******?班门弄斧起来了? 脸是自己拿来丢的,你有没有使用异常处理我还会不知道? 之前还有个誓言坦坦的,说他的WIN10 19041和别人的不一样的,假图都做出来了,我也装傻懒得鸟他了. https://bbs.pediy.com/thread-259760-1.htm#1645911 现在又来一个你这样的,我就很好奇你们这些人,这些问题是不是会**************, 死撑何求啊?认个输你会*********?死撑加狡辩,**************.
最后于 2020-6-8 22:14
被kanxue编辑
,原因:
|
能力值:
( LV3,RANK:21 )
|
-
-
24 楼
你自己试试不就知道了,你自己随便用个没有seh/veh的exe程序试试。 这个程序是《win32汇编语言程序设计琢石城器》第十三章里的。 还我装,我忍你很久了。 我一直都是礼貌的回答你,你骂骂咧咧的就算了。 还说我人品什么的,我一个小辈都不和你计较你还在那喋喋不休。 网络上面哔哔莱莱,现实世界碰一碰。
|
能力值:
( LV2,RANK:10 )
|
-
-
25 楼
老夫没试过会好像你这样张口就来? 你要现实是吧?125387我的Q,要约战打仗还是单P随便你,来. 你说不赢还想来打一场是吧?你如果真的认个错****************.
最后于 2020-6-8 22:16
被kanxue编辑
,原因: 请就事论事,勿人身攻击!以理服人!
|
|
|