pos机开机异常

 新闻资讯3  |   2023-08-22 09:20  |  投稿人:pos机之家

网上有很多关于pos机开机异常,NTDLL 异常处理在调试中的应用的知识,也有很多人为大家解答关于pos机开机异常的问题,今天pos机之家(www.poszjia.com)为大家整理了关于这方面的知识,让我们一起来看下吧!

本文目录一览:

1、pos机开机异常

pos机开机异常

顾名思义我们今天讨论的是应用层软件的调试,且是64位的软件,当一个软件发生错误或者异常时(不管是无意的还是刻意的)首先这个错误信息会先在内核中处理,如果是驱动程序产生的异常或者错误,能处理就处理不能处理就直接蓝屏,如果是应用程序的话,在内核中分配一些诸如ExceptionRecord、ContextRecord的结构体后就返回到用户层面继续处理了。

内核函数 KiExceptionDispatch在检测到异常或错误来自用户空间时,就会调用用户层的KiUserExceptionDispatcher,这个函数是用户层面的异常错误总入口,位于NTDLL.DLL中,我们编写软件时用到的SEH异常处理,都是由这个函数来实现的。

上图是win10的目前最新的版本

我们看下它的导出函数KiUserExceptionDispatcher,其中RtlDispatchException就是核心的异常处理过程,RtlGuardRestoreContext 函数是调用我们提供给SEH的安全返回地址。

现在市面上的商业软件不管32位还是64位,都有防跟踪、防逆向的指令在保护自身代码,很多调试器也有相应的插件提供过保护,32位系统下,基本上OD可以过所有保护。但64位系统下就不行了,其中win64对内核有更加严格的保护,不像32位下你可以随时接管中断接口、异常接口、SSDT 等,64位系统下你这样做分分钟蓝屏,PatchGuard了解一下。

基于这个原因,其实我们可以从ntdll的RtlDispatchException函数入手,我们挂钩RtlDispatchException,接管用户层面的所有异常,然后过滤出我们感兴趣的程序即可。

我们增加一个新的节区(fix)调整节区属性为可读、可写、可执行、可共享(应用程序加载NTDLL时不会为这个节区额外分配空间,直接映射我们分配的空间)

手动修改call的跳转地址。然后自己编写过滤代码,将编好的代码用ue写入我们新建的节区就可以了。假如我们要跟踪一个license 授权文件的解密流程,那就需要挂钩ZwCreateFile函数,获取到文件句柄后,挂钩ZwReadFile函数。方法和RtlDispatchException一样,直接把指令call到我们提前定义的空间地址上。整个过程就是在真实的环境中运行,软件自身的反调试功能统统失效,因为我们就没用市面上的任何调试器,我们直接通过和NTDLL的自定义节区(fix)交换数据来获取调试数据。

很多软件喜欢用VMP来加壳,我们就针对VMP来简单说下调试过程吧。VMP壳软件在启动过程中自身会调用一些函数来检测电脑的运行环境,如果电脑处在调试模式,或者检测到调试端口、事件之类,就会异常退出,我们没用调试器所以就不用关心这些事情,唯一要做的是VMP对自陷指令的处理,比如:int1 、int 3。我们不是接管了RtlDispatchException嘛,所以VMP 产生的异常指令,都会被我们过滤到,把这些过滤到的异常指令全部保存下来,将来在动态跟踪时,遇到这些指令就放行。

pushfq

or byte ptr [rsp+1],1 ;单步

popfq

持续产生int1 中断,就可以把整个代码流程给抓取出来。用正确的授权走一遍,再用错误的走一遍,比对一下不同点很快就可以找到关键 jz jnz 指令点。

align 16org 300hdq 0cccccccccccccccchdq 0cccccccccccccccch_DispatchException procLOCAL @OBJECT_ATTRIBUTES :OBJECT_ATTRIBUTES ;30hLOCAL @seh_64_exe_UNICODE_STRING :UNICODE_STRING ;<?>;10hLOCAL ip:qwordLOCAL @SectionHandle:qwordLOCAL @LARGE_INTEGER:qwordLOCAL @SectionOffset:qwordLOCAL @ViewSize:qwordLOCAL @viewBaseAddress:qwordLOCAL @PEB_LDR_DATA :qwordLOCAL @NEXT_PEB_LDR_DATA:qword ;要调试的程序的文件名LOCAL @NEXT__for_all_PEB_LDR_DATA:qword ;要调试的程序所包含的全部DLL信息LOCAL @flags_debug_or_nodebug:qwordLOCAL @hevent_read_for_seh_64 :qwordLOCAL @hevent_write_for_ntdll :qword ;NTDLL可以写数据了LOCAL @DllBase :qwordLOCAL _rcx:qword; ExceptionRecordLOCAL _rdx:qword;ContextRecordLOCAL _rsi:qwordLOCAL _rdi:qwordLOCAL _r8:qwordLOCAL _r9:qwordLOCAL _r10:qwordLOCAL _r11:qwordLOCAL _r12:qword, _r13:qword, _r14:qword, _r15:qwordLOCAL @ObjectDirectory:qwordLOCAL @count:qwordmov _rcx,rcxmov _rdx,rdxmov _rsi,rsimov _rdi,rdimov _r8,r8mov _r9,r9mov _r10,r10mov _r11,r11push rcxpush rdxpush rbxpush rbppush rsipush rdipush r12push r13push r14push r15sub rsp, 80hcall @f@@:pop raxlea rbx,@bsub rax,rbxmov ip,raxmov rsi,[rdx+_CONTEXT._Rip]lea rdi, track_pointadd rdi,raxlea rbx, track_point_endadd rbx,rax.if << cmp rsi,rdi>>, ABOVE?||EQUAL? ;可能产生异常的地方,处理方法.if <<cmp rsi,rbx>> , BELOW?||EQUAL? ;如果是我们自己的RtlDispatchException 产生的异常,那就跳过这个异常的记录, mov rsi,[rsi+ _CONTEXT._Rip];.if <<test rsi,rsi>>, NOZERO?;REP MOVSB 这个很容易产生异常;.else;mov qword ptr [rdi],0;.endiflea rbx,track_point_endmov [rdx+_CONTEXT._Rip],rbxadd rsp,80hpop r15pop r14pop r13pop r12pop rdipop rsipop rbppop rbxpop rdxpop rcxmov r8,_r8mov r9,_r9mov r10,_r10mov r11,_r11; mov rax,1 ;RtlDispatchException 返回1 之后RtlRestoreContext 继续执行; ret ;不能直接返回:RtlRestoreContext 已经被我们HOOK,会生成单步中断mov rax,iplea rax,[rax+78e9b39fh] ; RtlRestoreContext;text:0000000078E9BCC1 E8 D9 F6 FF FF call RtlRestoreContext ; VOID WINAPI RtlRestoreContext( ;文件地址: 4b0c1 更改为E8 3afb1500 call near ptr qword_78FFb800mov rcx,_rcxmov rdx,_rdxmov rcx,rdx ;contextxor rdx,rdxleave;jmp qword ptr _r11jmp rax.endif.endifmov rsi,[rdx+_CONTEXT._Rip]lea rdi, copy_ripadd rdi,raxlea rbx, copy_rip_endadd rbx,rax.if << cmp rsi,rdi>>, ABOVE?||EQUAL? ;可能产生异常的地方,处理方法.if <<cmp rsi,rbx>> , BELOW?||EQUAL? ;如果是我们自己的RtlDispatchException 产生的异常,那就跳过这个异常的记录, mov rsi,[rsi+ _CONTEXT._Rip];.if <<test rsi,rsi>>, NOZERO?;REP MOVSB 这个很容易产生异常;.else;mov qword ptr [rdi],0;.endiflea rbx,copy_rip_endmov [rdx+_CONTEXT._Rip],rbxadd rsp,80hpop r15pop r14pop r13pop r12pop rdipop rsipop rbppop rbxpop rdxpop rcxmov r8,_r8mov r9,_r9mov r10,_r10mov r11,_r11; mov rax,1 ;RtlDispatchException 返回1 之后RtlRestoreContext 继续执行; ret ;不能直接返回:RtlRestoreContext 已经被我们HOOK,会生成单步中断mov rax,iplea rax,[rax+78e9b39fh] ; RtlRestoreContext;text:0000000078E9BCC1 E8 D9 F6 FF FF call RtlRestoreContext ; VOID WINAPI RtlRestoreContext( ;文件地址: 4b0c1 更改为E8 3afb1500 call near ptr qword_78FFb800mov rcx,_rcxmov rdx,_rdxmov rcx,rdx ;contextxor rdx,rdxleave;jmp qword ptr _r11jmp rax.endif.endiflea rdi,copy_in_data_rbpadd rdi,raxlea rbx,copy_in_rbp_endadd rbx,rax.if << cmp rsi,rdi>>, ABOVE?||EQUAL? ;可能产生异常的地方,处理方法.if <<cmp rsi,rbx>> ,BELOW?||EQUAL?mov rax,iplea rbx,copy_in_rbp_endmov [rdx+_CONTEXT._Rip],rbxadd rsp,80hpop r15pop r14pop r13pop r12pop rdipop rsipop rbppop rbxpop rdxpop rcxmov r8,_r8mov r9,_r9mov r10,_r10mov r11,_r11; mov rax,1 ;RtlDispatchException 返回1 之后RtlRestoreContext 继续执行; ret ;不能直接返回:RtlRestoreContext 已经被我们HOOK,会生成单步中断mov rax,iplea rax,[rax+78e9b39fh] ; RtlRestoreContext;text:0000000078E9BCC1 E8 D9 F6 FF FF call RtlRestoreContext ; VOID WINAPI RtlRestoreContext( ;文件地址: 4b0c1 更改为E8 3afb1500 call near ptr qword_78FFb800mov rcx,_rcxmov rdx,_rdxmov rcx,rdx ;contextxor rdx,rdxleave;jmp qword ptr _r11jmp rax.endif.endiflea rdi,[rax+78ffa060h]lea rbx,[rax+78ffa0e0h].if << cmp rsi,rdi>>, ABOVE?||EQUAL?.if <<cmp rsi,rbx>> ,BELOW?||EQUAL?mov rax,iplea rbx,[rax+78ffa0e0h] ;这里存放的是ret指令(POP RCX POP RDI POP RSI RETmov [rdx+_CONTEXT._Rip],rbxadd rsp,80hpop r15pop r14pop r13pop r12pop rdipop rsipop rbppop rbxpop rdxpop rcxmov r8,_r8mov r9,_r9mov r10,_r10mov r11,_r11; mov rax,1 ;RtlDispatchException 返回1 之后RtlRestoreContext 继续执行; ret ;不能直接返回:RtlRestoreContext 已经被我们HOOK,会生成单步中断mov rax,iplea rax,[rax+78e9b39fh] ; RtlRestoreContext;text:0000000078E9BCC1 E8 D9 F6 FF FF call RtlRestoreContext ; VOID WINAPI RtlRestoreContext( ;文件地址: 4b0c1 更改为E8 3afb1500 call near ptr qword_78FFb800mov rcx,_rcxmov rdx,_rdxmov rcx,rdx ;contextxor rdx,rdxleave;jmp qword ptr _r11jmp rax.endif.endif.if <<cmp [rdx+_CONTEXT._Rax],12121212h>>,ZERO?.if <<cmp [rdx+ _CONTEXT._Rbx],23232323h>>,ZERO?.if <<cmp [rdx+_CONTEXT._Rcx],34343434h>>,ZERO?.if <<cmp [rdx+ _CONTEXT._Rdx],45454545h>>,ZERO?;确认是我们的调试器发出的指令mov rax,[rdx+_CONTEXT._R12]mov @flags_debug_or_nodebug,raxmov rax,[rdx+_CONTEXT._R13] ;sizeof_filemov @hevent_read_for_seh_64,0mov rax,[rdx+_CONTEXT._R14]mov @hevent_write_for_ntdll,0mov rax,iplea rax, [rax+78efb2f0h];call rax ;ntdll!RtlGetCurrentPeb.if <<test rax,rax>>,NOZERO?mov rax,[rax+18h] ;_PEB_LDR_DATA.if <<test rax,rax>>,NOZERO?lea rcx, [rax+10h]mov @PEB_LDR_DATA,rcxmov rax,[rax+10h];_PEB_LDR_DATA.InLoadOrderModuleList;InLoadOrderModuleList : _LIST_ENTRY.if <<test rax,rax>>,NOZERO?.while <<cmp rax,@PEB_LDR_DATA>>,NOZERO?lea rax,[rax+LIST_ENTRY.Flink]mov @NEXT_PEB_LDR_DATA,raxmov rbx,[rax+30h];_LDR_DATA_TABLE_ENTRY.DllBasemov @DllBase,rbxlea rax,[rax+58h]; _LDR_DATA_TABLE_ENTRY.BaseDllName : _UNICODE_STRING; mov rsi,[rax+_UNICODE_STRING.Buffer]; invoke MessageBoxW,0,rsi,addr ldrtest,MB_OKmovzx rcx,[rax+_UNICODE_STRING._Length]mov rsi,[rax+_UNICODE_STRING.Buffer]mov rax,iplea rdi ,[rax+78ffa010h] ;szMMFName db "seh_64.exe64---",0cldrepz cmpsb.if ZERO? ;是seh_64发出的异常指令mov rdx,_rdxlea rsi , [rdx+_CONTEXT._Rsi];_rsi--_r11 总共30H 存放有要调试的程序mov ecx,30hmov rax,iplea rdi ,[rax+78ffa030h+8]cldrep movsbmov rcx,[rdx+_CONTEXT._R15]mov qword ptr [rax+78ffa030h],rcxlea rsi , [rdx+_CONTEXT.___u38.data.__s1._Xmm0]lea rdi ,[rax+78ffa200h]mov rcx,20hcldrep movsqmov rcx,@flags_debug_or_nodebugmov [rax+78ffa100h],rcx ;1自动跟踪MT5 或 0只是检测它的异常断点 -1,动态调试mov rdx,_rdxmov rcx,8989898989898989hmov [rdx+_CONTEXT._Rax],rcxmov rcx,9a9a9a9a9a9a9a9ahmov [rdx+_CONTEXT._Rbx],rcxmov rcx,0ababababababababhmov [rdx+_CONTEXT._Rcx],rcxmov rcx,0bcbcbcbcbcbcbcbchmov [rdx+_CONTEXT._Rdx],rcxmov rax,ipmov rcx,78ffc000hadd rcx,raxmov [rdx+_CONTEXT._Rsi],rcx ;@viewBaseAddressmov rcx,78ffa0f8hadd rcx,raxmov [rdx+_CONTEXT._Rdi],rcx ;@hevent_write_for_ntdll;NTDLL可以写数据了mov rcx,78ffa0f0hadd rcx,raxmov [rdx+_CONTEXT._R9],rcx ;;hevent_read_for_seh_64mov rcx,78ffc000hadd rcx,raxmov @viewBaseAddress,rcxlock and qword ptr [rax+78ffa008h],0;@viewBaseAddresslock or [rax+78ffa008h],rcxlock and qword ptr [rax+78ffa000h],0;第一次运行需要获取程序需要的DLL信息lock and qword ptr [rax+78ffa110h],0;进程IDlock and qword ptr [rax+78ffa120h],0;78ffa120h license.lic 文件句柄mov rcx,[rdx+_CONTEXT._R13] ;sizeof_filemov qword ptr [rax+78ffa118h],rcx;被调试程序大小mov rcx,[rdx+_CONTEXT._R14];lock and qword ptr [rax+78ffa108h],0lock or qword ptr [rax+78ffa108h],rcx;总开关,系统在初始化时,不需要任何检测的,我们的调试器还没有启动呢!add qword ptr [rdx+_CONTEXT._Rip],8 ; C6 04 25 00 00 00 00 00 mov byte ptr ds:0, 0mov rax,ipadd rsp,80hpop r15pop r14pop r13pop r12pop rdipop rsipop rbppop rbxpop rdxpop rcxmov r8,_r8mov r9,_r9mov r10,_r10mov r11,_r11mov rax,1 ;RtlDispatchException 返回1 之后RtlRestoreContext 继续执行ret.endifmov rax, @NEXT_PEB_LDR_DATAmov rax,[rax].endw.endif.endif.endif.endif.endif.endif.endif;是否MT5产生的异常mov rax,ipmov rcx,[rax+78ffa108h] ;总开关,系统在初始化时,不需要任何检测了.if <<test rcx,rcx>>, ZERO?jmp exit.endifmov rax,ipmov rcx,[rax+78ffa110h]mov rax,qword ptr gs:[30h] ;_TEB. _NT_TIB.selfmov eax,dword ptr [rax+40h];GetCurrentProcessId ;ClientId._CLIENT_ID.UniqueProcess.if <<test rcx,rcx>>, NOZERO? ;进程ID.if <<cmp rcx,rax>>, NOZERO?jmp exit ;不是我们要处理的程序.endif.else ;如果进程ID为空说明之前还没有捕获到MT5的异常 这里继续在本次异常里尝试mov rax,iplea rax, [rax+78efb2f0h];call rax ;ntdll!RtlGetCurrentPeb.if <<test rax,rax>>,NOZERO?mov rax,[rax+18h] ;_PEB_LDR_DATA.if <<test rax,rax>>,NOZERO?lea rcx, [rax+10h]mov @PEB_LDR_DATA,rcxmov rax,[rax+10h];_PEB_LDR_DATA.InLoadOrderModuleList;InLoadOrderModuleList : _LIST_ENTRY.if <<test rax,rax>>,NOZERO?.while <<cmp rax,@PEB_LDR_DATA>>,NOZERO?; lea rax,[rax+LIST_ENTRY.Flink];;其实这里还是== lea rax,[rax] ;LIST_ENTRY.Flink == 0mov @NEXT_PEB_LDR_DATA,raxmov rbx,[rax+30h];_LDR_DATA_TABLE_ENTRY.DllBasemov @DllBase,rbxlea rax,[rax+58h]; _LDR_DATA_TABLE_ENTRY.BaseDllName : _UNICODE_STRINGmovzx rcx,[rax+_UNICODE_STRING._Length]mov rbx,ip.if <<cmp rcx,[rbx+78ffa030h]>>,zero? ; 要调试的程序名长度mov rsi,[rax+_UNICODE_STRING.Buffer]mov rax,iplea rdi ,[rax+78ffa030h+8]cldrepz cmpsb.if ZERO? ;MT5的异常;这里找到MT5了;保存加载的DLL信息和进程IDmov rax,ipmov rcx,@DllBasemov [rax+78ffa0e8h],rcxmov rcx,[rax+78ffa000h].if <<test rcx,rcx>>,ZERO? ;第一次运行需要获取程序需要的DLL信息comment ~lea rcx,@seh_64_exe_UNICODE_STRINGlea rdx, [rax+78ffa010h+8]lea rax,[rax+78e9f5d0h]call rax ;RtlInitUnicodeStringlea rcx,@ObjectDirectorymov rax,iplea rax, [rax+78EF7FA0h];call rax;BaseGetNamedObjectDirectorymov rax,iplea rdx,@seh_64_exe_UNICODE_STRINGlea rcx,@OBJECT_ATTRIBUTESmov rax,@ObjectDirectoryInitializeObjectAttributes rcx, rdx, OBJ_OPENIF, rax, NULL;OBJ_OPENIF equ 80hlea r8,@OBJECT_ATTRIBUTESmov rdx,EVENT_ALL_ACCESSlea rcx,@hevent_read_for_seh_64mov rax,iplea rax, [rax+78e9c130h]call rax ;ZwOpenEvent returns STATUS_SUCCESS on success.if <<test rax,rax>>, NOZERO?jmp exit.endifmov rax,ipmov rcx,@hevent_read_for_seh_64;mov [rax+78ffa0f0h],rcxlea rcx,@seh_64_exe_UNICODE_STRINGlea rdx, [rax+78ffa010h+10H]lea rax,[rax+78e9f5d0h]call rax ;RtlInitUnicodeStringlea rcx,@ObjectDirectorymov rax,iplea rax, [rax+78EF7FA0h];call rax;BaseGetNamedObjectDirectorymov rax,iplea rdx,@seh_64_exe_UNICODE_STRINGlea rcx,@OBJECT_ATTRIBUTESmov rax,@ObjectDirectoryInitializeObjectAttributes rcx, rdx, OBJ_OPENIF, rax, NULL;OBJ_OPENIF equ 80hlea r8,@OBJECT_ATTRIBUTESmov rdx,EVENT_ALL_ACCESSlea rcx,@hevent_write_for_ntdllmov rax,iplea rax, [rax+78e9c130h]call rax ;ZwOpenEvent returns STATUS_SUCCESS on success.if <<test rax,rax>>, NOZERO?jmp exit.endifmov rax,ipmov rcx,@hevent_write_for_ntdll;NTDLL可以写数据了mov [rax+78ffa0f8h],rcxlea rcx,@seh_64_exe_UNICODE_STRINGlea rdx, [rax+78ffa010h]lea rax,[rax+78e9f5d0h]call rax ;RtlInitUnicodeStringlea rcx,@ObjectDirectorymov rax,iplea rax, [rax+78EF7FA0h];call rax;BaseGetNamedObjectDirectorymov rax,iplea rdx,@seh_64_exe_UNICODE_STRINGlea rcx,@OBJECT_ATTRIBUTESmov rax,@ObjectDirectoryInitializeObjectAttributes rcx, rdx, OBJ_OPENIF, rax, NULL;OBJ_OPENIF equ 80hlea r8,@OBJECT_ATTRIBUTESmov rdx,SECTION_MAP_WRITE or SECTION_MAP_READ ;SECTION_MAP_WRITE equ 2h SECTION_MAP_READ equ 4hlea rcx,@SectionHandlemov rax,iplea rax, [rax+78e9c0a0h]call rax ;ZwOpenSection returns STATUS_SUCCESS on success.if <<test rax,rax>>,ZERO?mov rcx,@SectionHandlemov rdx,-1;ProcessHandlelea r8,@viewBaseAddressmov @viewBaseAddress,0mov r9,0;ZeroBits,mov qword ptr [rsp+20h],0;CommitSizelea rax,@SectionOffsetmov @SectionOffset,0mov qword ptr [rsp+28h],rax;SectionOffsetlea rax,@ViewSizemov @ViewSize,0mov qword ptr [rsp+30h],rax;ViewSize 分配的尺寸mov qword ptr [rsp+38h],1;ViewShare equ 1mov qword ptr [rsp+40h],0mov qword ptr [rsp+48h],PAGE_READWRITE ; equ 4mov dword ptr [rsp+4ch],-1mov rax,iplea rax, [rax+78e9bfb0h]call rax ;ntdll!ZwMapViewOfSection PROTO64 external,ZwMapViewOfSection,; :QWORD,:QWORD,:QWORD,:QWORD,:QWORD,:QWORD,:QWORD,:QWORD,:QWORD,:QWORD.if <<test rax,rax>>,ZERO?comment ~mov rax,ipmov rcx,1mov @SectionHandle,rcx; lock and qword ptr [rax+78ffa000h],0;第一次运行需要获取程序需要的DLL信息; lock or [rax+78ffa000h],rcxlock xchg [rax+78ffa000h],rcxmov rax,iplea rax, [rax+78efb2f0h];call rax ;ntdll!RtlGetCurrentPeb.if <<test rax,rax>>,NOZERO?mov rax,[rax+18h] ;_PEB_LDR_DATA.if <<test rax,rax>>,NOZERO?lea rcx, [rax+10h]mov @PEB_LDR_DATA,rcxmov rax,[rax+10h];_PEB_LDR_DATA.InLoadOrderModuleList;InLoadOrderModuleList : _LIST_ENTRY.if <<test rax,rax>>,NOZERO?;把找到的dll信息发给调试器mov @NEXT_PEB_LDR_DATA,rax; mov rax,ip; mov rcx,[rax+78ffa0f8h];;NTDLL可以写数据了; mov rdx,0; mov r8,0; lea rax, [rax+78e9bd70h];; call rax ;ntdll!ZwWaitForSingleObjectmov rax,ip@@:lock bts qword ptr [rax+78ffa0f8h], 0 ; BTS就是根据位偏移值从位串中取出一位放入CF中,然后将位串中的该位置成1jnc @f_wait:pausewaitfwaittest qword ptr [rax+78ffa0f8h], 1jnz _waitjmp @b@@:mov rax, @NEXT_PEB_LDR_DATAmov rbx,0.while <<cmp rax,@PEB_LDR_DATA>>,NOZERO?; lea rax,[rax+LIST_ENTRY.Flink]mov @NEXT_PEB_LDR_DATA,raxmov rdx,[rax+30h];_LDR_DATA_TABLE_ENTRY.DllBaselea rax,[rax+58h]; _LDR_DATA_TABLE_ENTRY.BaseDllName : _UNICODE_STRINGmovzx rcx,[rax+_UNICODE_STRING._Length];我们设置的长度是40h unicode模式 是ASCII码长度的2倍.if <<cmp rcx,40h>>, BELOW?||EQUAL?mov rsi,[rax+_UNICODE_STRING.Buffer]mov rax,ipmov rdi,[rax+78ffa008h];@viewBaseAddressmov [rdi][rbx][dllinformation.flags],2mov [rdi][rbx][dllinformation.dllbase],rdxmov [rdi][rbx][dllinformation.dllnamelength],rcxlea rdi,[rdi][rbx][dllinformation.dllname]cldrep movsbadd rbx,sizeof dllinformation.if <<cmp rbx,40*sizeof dllinformation>>, ABOVE?.break.endif.endifmov rax,@NEXT_PEB_LDR_DATAmov rax,[rax+LIST_ENTRY.Flink].endwmov rcx,qword ptr gs:[30h]mov ecx,dword ptr [rcx+40h];GetCurrentProcessIdmov rax,iplock xchg [rax+78ffa110h],rcx;把进程id保存起来,下次直接通过ID比较; mov rcx,[rax+78ffa0f0h];hevent_read_for_seh_64; mov rdx,0; mov rax,ip; lea rax, [rax+78e9be10h];ZwSetEvent; call raxmov rax,iplock and qword ptr [rax+78ffa0f0h], 0 ; release spin lock hevent_read_for_seh_64 客户端可以读数据了.break ;跳出上一层循环.elsejmp error.endif.elsejmp error.endif.elsejmp error.endif.else.break ;如果已经设置好了,就不需要重复设置了.endif.endif.endifmov rax,@NEXT_PEB_LDR_DATAmov rax,[rax+LIST_ENTRY.Flink].endwmov rax,ipmov rcx,[rax+78ffa110h];进程ID.if <<test rcx,rcx>>, ZERO?;没有填充进程IDjmp exit.endif.elsejmp exit.endif.elsejmp exit.endif.elsejmp exit.endif.endif;这里确定是MT5后继续执行mov rax,ipmov rdi,[rax+78ffa0e8h] ;mt5DllBasemov @DllBase,rdi@@:lock bts qword ptr [rax+78ffa0f8h], 0 ; BTS就是根据位偏移值从位串中取出一位放入CF中,然后将位串中的该位置成1 ;;;;NTDLL可以写数据事件jnc @f_wait1:pausewaitfwaittest qword ptr [rax+78ffa0f8h], 1jnz _wait1jmp @b@@:mov rax,ipmov rdi,[rax+78ffa008h];@viewBaseAddressmov rax,qword ptr gs:[30h]mov eax,dword ptr [rax+40h];GetCurrentProcessIdmov qword ptr [rdi][recvfromntddd.flage_CONTEXT_EFlags],0mov qword ptr [rdi][recvfromntddd.flags],1mov qword ptr [rdi][recvfromntddd.from_processid],raxmov rax,qword ptr gs:[30h]mov eax,dword ptr [rax+48h];GetCurrentThreadId;_CLIENT_ID.UniqueThreadmov qword ptr [rdi][recvfromntddd.from_threadid],raxmov rax,@DllBasemov qword ptr [rdi][recvfromntddd.dllbase],raxlea rdi, [rdi+recvfromntddd.from_EXCEPTION_RECORD]mov rsi,_rcxmov rcx,sizeof EXCEPTION_RECORD.if <<test rsi,rsi>>, NOZERO?cldREP MOVSB.elsemov rax,0cccccccccccccccchcldrep stosb;mov qword ptr [rdi],rax.endifmov rax,ipmov rdi,[rax+78ffa008h];@viewBaseAddresslea rdi, [rdi+recvfromntddd.from__CONTEXT]mov rcx,sizeof _CONTEXTmov rsi,_rdx.if <<test rsi,rsi>>, NOZERO?cldREP MOVSB.elsemov al,90hcldrep stosb; mov qword ptr [rdi],rax;mov qword ptr [rdi],0.endif; mov rcx,sizeof DISPATCHER_CONTEXT; mov rsi,_r9; .if <<test rsi,rsi>>, NOZERO?; REP MOVSB; .endif; mov rsi,_r8mov rax,ipmov rdi,[rax+78ffa008h];@viewBaseAddresslea rdi, [rdi+recvfromntddd.from__Rip]mov rcx,11hmov rsi,_rdxmov rsi,[rsi+ _CONTEXT._Rip]copy_rip::.if <<test rsi,rsi>>, NOZERO?REP MOVSB.elsecopy_rip_end::mov rax,ipmov rdi,[rax+78ffa008h];@viewBaseAddresslea rdi, [rdi+recvfromntddd.from__Rip]mov rax,9090909090909090hmov qword ptr [rdi],raxmov word ptr [rdi],0cd04h;int 4mov qword ptr [rdi+8],raxmov byte ptr [rdi+10h],90h.endifmov rax,ipmov rdi,[rax+78ffa008h];@viewBaseAddresslea rdi, [rdi+recvfromntddd.RBP_0]mov rcx,2hmov rsi,_rdxmov rsi,[rsi+ _CONTEXT._Rbp]copy_in_data_rbp::.if <<test rsi,rsi>>, NOZERO?REP MOVSQ ;这里有可能RBP的地址会产生异常.elsecopy_in_rbp_end::mov rax,ipmov rdi,[rax+78ffa008h];@viewBaseAddresslea rdi, [rdi+recvfromntddd.RBP_0]mov rax,9090909090909090hmov qword ptr [rdi],raxmov qword ptr [rdi+8], rax.endifcomment ~;mov qword ptr[rsp+30],0;mov qword ptr[rsp+28],SEC_COMMIT;mov qword ptr [rsp+20],PAGE_READWRITE;lea r9,@LARGE_INTEGER;mov qword ptr [r9],1000h;lea r8,@OBJECT_ATTRIBUTES;mov rdx,0f0007h;lea rcx,@SectionHandle;mov rax,ip;lea rax, [rax+78e9c1d0h];call rax ;ZwCreateSection PROTO64 external,ZwCreateSection, :QWORD,:QWORD,:QWORD,:QWORD,:QWORD,:QWORD,:QWORD;test eax,eax;lea rax,[rax+78e78120h] ; RtlpExecuteHandlerForException 文件地址 1795a :E8 C1 FB 00 00 被替换为:text:0000000078E6855A E8 A1 1D 19 00 call near ptr qword_78FFA300; lea rax,[rax+78e68150h] ;;RtlpCallVectoredHandlers ;0000000078E681ED E8 5E FF FF FF 文件地址: 175ED 更改为E8 0e211900 call near ptr qword_78FFA300 call RtlpCallVectoredHandlers 已经替换了78E681ED的地址; mov _r11,rax;pop rax;要对VEH作个检测; mov r13d,2 ;VEH: 向量化异常处理程序(进程相关) mov r13d,3 对VCH检测; mov rax, qword ptr gs:[30h] ;teb; mov r12, [rax+60h] ;peb; mov eax, [r12+50h] ;ProcessUsingVEH; bt eax, r13d ; ;BT 把 eax 的第3位(或者 第2位根据 r8+2决定)复制到 CF 从0 开始排列; +0x050 ProcessUsingVEH : Pos 2, 1 Bit; +0x050 ProcessUsingVCH : Pos 3, 1 Bit; VEH: 向量化异常处理程序(进程相关); VCH: 同上,也是向量化异常处理程序,; 不过它总是在最后被调用(进程相关);VEH,VCH:保存在ntdll.dll模块的_LdrpVectorHandlerList全局变量里; .if CARRY?; .endif;0F 82 FD 16 00 00 jb loc_78E6988Dcomment ~mov rax,ipmov rcx,[rax+78ffa100h] ;1自动跟踪MT5 或 0只是检测它的异常断点 -1,动态调试.if <<test rcx,rcx>>, GREATER?;自动跟踪MT5mov rax,ipmov rsi,[rax+78ffa008h];@viewBaseAddresslea rsi,[rsi+4096+80h] ;这里存入的是官方的异常断点,这个值应该是个偏移量,因为程序每次装入的地址应该不一样。;前4 个字节是异常总共占用的大小mov ecx,[rsi+orgbreak.count_except]mov rbx,0mov rdi,_rdxmov rdi,[rdi+ _CONTEXT._Rip].while <<test rcx,rcx>>,NOZERO?mov rax,[rsi+orgbreak.except_point][rbx]add rax, @DllBase.if <<cmp rdi,rax>>, ZERO? ;官方的断点需要原程序自己去处理mov r8d,[rsi+orgbreak.except_flags][rbx];官方的断点要在 RtlpCallVectoredHandlers 里标记 还要在RtlRestoreContext里标记mov rax,iplock and qword ptr [rax+78ffa0f0h], 0 ; release spin lock,通知seh_64 接收数据add rsp,80hpop r15pop r14pop r13pop r12pop rdipop rsipop rbppop rbxpop rdxpop rcxmov r8,_r8mov r9,_r9mov r10,_r10mov r11,_r11mov rax,iplea rax,[rax+78e681d0h] ; RtlDispatchExceptionleavepushfq; or byte ptr [rsp+1],1 ;单步popfqjmp rax;这里不会返回了.endifadd rbx,sizeof orgbreakdec rcx.endwmov rsi,_rdxmov rax,[rsi+ _CONTEXT._Rip]track_point::.if <<cmp byte ptr [rax],09ch>>, ZERO?;;9c pushfq 如果当前INT1中断的地址内容是 pushfsub qword ptr [rsi+ _CONTEXT._Rsp],8 ;模拟pushfq 的执行mov eax,[rsi+ _CONTEXT.EFlags]and rax,0fffffffffffffeffh ;把tf 置0 if(中断标志) 用sti cli 修改,用户模式没有权限mov rbx,[rsi+ _CONTEXT._Rsp]mov [rbx],raxinc [rsi+ _CONTEXT._Rip];模拟pushf 之后 跳过pushf 的执行mov rax,ipmov rdi,[rax+78ffa008h];@viewBaseAddressmov qword ptr [rdi][recvfromntddd.flage_CONTEXT_EFlags],1;我们模拟pufhf 的执行 所以加个标志通知 seh_64。exe 处理这个情况track_point_end::and [rsi+ _CONTEXT.EFlags],0fffffeffh ;把tf和IF 置0OR [rsi+ _CONTEXT.EFlags],100Hmov rax,ipmov rdi,[rax+78ffa008h];@viewBaseAddressmov rax,[rsi+ _CONTEXT._Rip]jmp track_point ;或许有多个pushfq;ID VIP VIF AC VM RF NT IOPL OF DF IF TF SF ZF AF PF CF;21 20 19 18 17 16 14 13–12 11 10 9 8 7 6 4 2 0.elseif <<cmp word ptr [rax],09cf3h>>, ZERO?;;9cinc [rsi+ _CONTEXT._Rip];模拟pushf 之后 跳过pushf 的执行mov rax,[rsi+ _CONTEXT._Rip]jmp track_point.elseif <<cmp word ptr [rax],09c2eh>>, ZERO?;;9cinc [rsi+ _CONTEXT._Rip];模拟pushf 之后 跳过pushf 的执行mov rax,[rsi+ _CONTEXT._Rip]jmp track_point.elseif <<cmp word ptr [rax],09c40h>>, ZERO?;;9cinc [rsi+ _CONTEXT._Rip];模拟pushf 之后 跳过pushf 的执行mov rax,[rsi+ _CONTEXT._Rip]jmp track_point.elseOR [rsi+ _CONTEXT.EFlags],100H.endifmov rax,iplock and qword ptr [rax+78ffa0f0h], 0 ; release spin lock,通知seh_64 接收数据 release spin lock,通知seh_64 接收数据 release spin lock,通知seh_64 接收数据add rsp,80hpop r15pop r14pop r13pop r12pop rdipop rsipop rbppop rbxpop rdxpop rcxmov r8,_r8mov r9,_r9mov r10,_r10mov r11,_r11mov rax,1 ;RtlDispatchException 返回1 之后RtlRestoreContext 继续执行 我们HOOK的 RtlRestoreContext 会设置单步ret ;返回后继续调用RtlRestoreContext 这个RtlRestoreContext 调用不会再产生 异常,(我们没有设置 单步标志)下一次的异常是在返回用户地址后产生的.elseif <<test rcx,rcx>>, zero? ;1要调试MT5 或 0只是检测它的异常断点 -1,动态调试mov rax,iplock and qword ptr [rax+78ffa0f0h], 0 ; release spin lock,通知seh_64 接收数据.elsemov rax,iplock and qword ptr [rax+78ffa0f0h], 0 ; release spin lock,通知seh_64 接收数据 release spin lock,通知seh_64 接收数据 release spin lock,通知seh_64 接收数据_80h_instruct:mov rax,ip@@:lock bts qword ptr [rax+78ffa0f8h], 0 ; BTS就是根据位偏移值从位串中取出一位放入CF中,然后将位串中的该位置成1jnc @f_wait2:pausewaitfwaittest qword ptr [rax+78ffa0f8h], 1jnz _wait2jmp @b@@:mov rax,ipmov rsi,[rax+78ffa008h];@viewBaseAddress 78ffc000mov qword ptr [rsi][recvfromntddd.flags],0lea rsi,[rsi+4096] ;78ffd000h单步调试指令区 sizeof == 80h.if <<cmp byte ptr [rsi],0>>,NOZERO? ;这里是指令区lea rdi,[rax+78ffa060h]mov rcx,10hrep movsq ;读80h个指令mov rcx,_rcxmov rdx,_rdxlea rbx,[rax+78ffa060h]call rbx;qword ptr [rax+78ffa060h] ;80H字节的指令区mov rax,iplock and qword ptr [rax+78ffa0f0h], 0 ; release spin lock,通知seh_64 接收数据 release spin lock,通知seh_64 接收数据 release spin lock,通知seh_64 接收数据jmp _80h_instructnop.elsemov rax,iplock and qword ptr [rax+78ffa0f0h], 0 ; release spin lock,通知seh_64 接收数据 release spin lock,通知seh_64 接收数据 release spin lock,通知seh_64 接收数据.endifadd rsp,80hpop r15pop r14pop r13pop r12pop rdipop rsipop rbppop rbxpop rdxpop rcxmov r8,_r8mov r9,_r9mov r10,_r10mov r11,_r11; mov rax,1 ;RtlDispatchException 返回1 之后RtlRestoreContext 继续执行; ret ;不能直接返回:RtlRestoreContext 已经被我们HOOK,会生成单步中断mov rax,iplea rax,[rax+78e9b39fh] ; RtlRestoreContext;text:0000000078E9BCC1 E8 D9 F6 FF FF call RtlRestoreContext ; VOID WINAPI RtlRestoreContext( ;文件地址: 4b0c1 更改为E8 3afb1500 call near ptr qword_78FFb800mov rcx,_rcxmov rdx,_rdxmov rcx,rdx ;contextxor rdx,rdxleave;jmp qword ptr _r11jmp rax.endiferror_DispatchException::error:exit: ;不是我们需要的add rsp,80hpop r15pop r14pop r13pop r12pop rdipop rsipop rbppop rbxpop rdxpop rcxmov r8,_r8mov r9,_r9mov r10,_r10mov r11,_r11mov rax,ip;lea rax,[rax+78e78120h] ; RtlpExecuteHandlerForException 文件地址 1795a :E8 C1 FB 00 00 被替换为:text:0000000078E6855A E8 A1 1D 19 00 call near ptr qword_78FFA300;lea rax,[rax+78e68150h] ;;RtlpCallVectoredHandlers ;0000000078E681ED E8 5E FF FF FF 文件地址: 175ED 更改为E8 0e211900 call near ptr qword_78FFA300 call RtlpCallVectoredHandlers 已经替换了78E681ED的地址lea rax,[rax+78e681d0h] ; RtlDispatchException;.text:0000000078E9BCB3 E8 18 C5 FC FF call RtlDispatchException ;文件地址: 4b0b4 更改为E8 48e61500 call near ptr qword_78FFA300; mov _r11,rax;pop rax;jmp qword ptr _r11leavejmp rax;call rax 这里不能用CALL 会破坏堆栈平衡ret_DispatchException endp

以上就是关于pos机开机异常,NTDLL 异常处理在调试中的应用的知识,后面我们会继续为大家整理关于pos机开机异常的知识,希望能够帮助到大家!

转发请带上网址:http://www.poszjia.com/newstwo/102299.html

你可能会喜欢:

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 babsan@163.com 举报,一经查实,本站将立刻删除。