pos機(jī)開(kāi)機(jī)異常

 新聞資訊3  |   2023-08-22 09:20  |  投稿人:pos機(jī)之家

網(wǎng)上有很多關(guān)于pos機(jī)開(kāi)機(jī)異常,NTDLL 異常處理在調(diào)試中的應(yīng)用的知識(shí),也有很多人為大家解答關(guān)于pos機(jī)開(kāi)機(jī)異常的問(wèn)題,今天pos機(jī)之家(www.shbwcl.net)為大家整理了關(guān)于這方面的知識(shí),讓我們一起來(lái)看下吧!

本文目錄一覽:

1、pos機(jī)開(kāi)機(jī)異常

pos機(jī)開(kāi)機(jī)異常

顧名思義我們今天討論的是應(yīng)用層軟件的調(diào)試,且是64位的軟件,當(dāng)一個(gè)軟件發(fā)生錯(cuò)誤或者異常時(shí)(不管是無(wú)意的還是刻意的)首先這個(gè)錯(cuò)誤信息會(huì)先在內(nèi)核中處理,如果是驅(qū)動(dòng)程序產(chǎn)生的異常或者錯(cuò)誤,能處理就處理不能處理就直接藍(lán)屏,如果是應(yīng)用程序的話,在內(nèi)核中分配一些諸如ExceptionRecord、ContextRecord的結(jié)構(gòu)體后就返回到用戶(hù)層面繼續(xù)處理了。

內(nèi)核函數(shù) KiExceptionDispatch在檢測(cè)到異常或錯(cuò)誤來(lái)自用戶(hù)空間時(shí),就會(huì)調(diào)用用戶(hù)層的KiUserExceptionDispatcher,這個(gè)函數(shù)是用戶(hù)層面的異常錯(cuò)誤總?cè)肟冢挥贜TDLL.DLL中,我們編寫(xiě)軟件時(shí)用到的SEH異常處理,都是由這個(gè)函數(shù)來(lái)實(shí)現(xiàn)的。

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

我們看下它的導(dǎo)出函數(shù)KiUserExceptionDispatcher,其中RtlDispatchException就是核心的異常處理過(guò)程,RtlGuardRestoreContext 函數(shù)是調(diào)用我們提供給SEH的安全返回地址。

現(xiàn)在市面上的商業(yè)軟件不管32位還是64位,都有防跟蹤、防逆向的指令在保護(hù)自身代碼,很多調(diào)試器也有相應(yīng)的插件提供過(guò)保護(hù),32位系統(tǒng)下,基本上OD可以過(guò)所有保護(hù)。但64位系統(tǒng)下就不行了,其中win64對(duì)內(nèi)核有更加嚴(yán)格的保護(hù),不像32位下你可以隨時(shí)接管中斷接口、異常接口、SSDT 等,64位系統(tǒng)下你這樣做分分鐘藍(lán)屏,PatchGuard了解一下。

基于這個(gè)原因,其實(shí)我們可以從ntdll的RtlDispatchException函數(shù)入手,我們掛鉤RtlDispatchException,接管用戶(hù)層面的所有異常,然后過(guò)濾出我們感興趣的程序即可。

我們?cè)黾右粋€(gè)新的節(jié)區(qū)(fix)調(diào)整節(jié)區(qū)屬性為可讀、可寫(xiě)、可執(zhí)行、可共享(應(yīng)用程序加載NTDLL時(shí)不會(huì)為這個(gè)節(jié)區(qū)額外分配空間,直接映射我們分配的空間)

手動(dòng)修改call的跳轉(zhuǎn)地址。然后自己編寫(xiě)過(guò)濾代碼,將編好的代碼用ue寫(xiě)入我們新建的節(jié)區(qū)就可以了。假如我們要跟蹤一個(gè)license 授權(quán)文件的解密流程,那就需要掛鉤ZwCreateFile函數(shù),獲取到文件句柄后,掛鉤ZwReadFile函數(shù)。方法和RtlDispatchException一樣,直接把指令call到我們提前定義的空間地址上。整個(gè)過(guò)程就是在真實(shí)的環(huán)境中運(yùn)行,軟件自身的反調(diào)試功能統(tǒng)統(tǒng)失效,因?yàn)槲覀兙蜎](méi)用市面上的任何調(diào)試器,我們直接通過(guò)和NTDLL的自定義節(jié)區(qū)(fix)交換數(shù)據(jù)來(lái)獲取調(diào)試數(shù)據(jù)。

很多軟件喜歡用VMP來(lái)加殼,我們就針對(duì)VMP來(lái)簡(jiǎn)單說(shuō)下調(diào)試過(guò)程吧。VMP殼軟件在啟動(dòng)過(guò)程中自身會(huì)調(diào)用一些函數(shù)來(lái)檢測(cè)電腦的運(yùn)行環(huán)境,如果電腦處在調(diào)試模式,或者檢測(cè)到調(diào)試端口、事件之類(lèi),就會(huì)異常退出,我們沒(méi)用調(diào)試器所以就不用關(guān)心這些事情,唯一要做的是VMP對(duì)自陷指令的處理,比如:int1 、int 3。我們不是接管了RtlDispatchException嘛,所以VMP 產(chǎn)生的異常指令,都會(huì)被我們過(guò)濾到,把這些過(guò)濾到的異常指令全部保存下來(lái),將來(lái)在動(dòng)態(tài)跟蹤時(shí),遇到這些指令就放行。

pushfq

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

popfq

持續(xù)產(chǎn)生int1 中斷,就可以把整個(gè)代碼流程給抓取出來(lái)。用正確的授權(quán)走一遍,再用錯(cuò)誤的走一遍,比對(duì)一下不同點(diǎn)很快就可以找到關(guān)鍵 jz jnz 指令點(diǎn)。

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 ;要調(diào)試的程序的文件名LOCAL @NEXT__for_all_PEB_LDR_DATA:qword ;要調(diào)試的程序所包含的全部DLL信息LOCAL @flags_debug_or_nodebug:qwordLOCAL @hevent_read_for_seh_64 :qwordLOCAL @hevent_write_for_ntdll :qword ;NTDLL可以寫(xiě)數(shù)據(jù)了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? ;可能產(chǎn)生異常的地方,處理方法.if <<cmp rsi,rbx>> , BELOW?||EQUAL? ;如果是我們自己的RtlDispatchException 產(chǎn)生的異常,那就跳過(guò)這個(gè)異常的記錄, mov rsi,[rsi+ _CONTEXT._Rip];.if <<test rsi,rsi>>, NOZERO?;REP MOVSB 這個(gè)很容易產(chǎn)生異常;.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 繼續(xù)執(zhí)行; ret ;不能直接返回:RtlRestoreContext 已經(jīng)被我們HOOK,會(huì)生成單步中斷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? ;可能產(chǎn)生異常的地方,處理方法.if <<cmp rsi,rbx>> , BELOW?||EQUAL? ;如果是我們自己的RtlDispatchException 產(chǎn)生的異常,那就跳過(guò)這個(gè)異常的記錄, mov rsi,[rsi+ _CONTEXT._Rip];.if <<test rsi,rsi>>, NOZERO?;REP MOVSB 這個(gè)很容易產(chǎn)生異常;.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 繼續(xù)執(zhí)行; ret ;不能直接返回:RtlRestoreContext 已經(jīng)被我們HOOK,會(huì)生成單步中斷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? ;可能產(chǎn)生異常的地方,處理方法.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 繼續(xù)執(zhí)行; ret ;不能直接返回:RtlRestoreContext 已經(jīng)被我們HOOK,會(huì)生成單步中斷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 繼續(xù)執(zhí)行; ret ;不能直接返回:RtlRestoreContext 已經(jīng)被我們HOOK,會(huì)生成單步中斷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?;確認(rèn)是我們的調(diào)試器發(fā)出的指令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發(fā)出的異常指令mov rdx,_rdxlea rsi , [rdx+_CONTEXT._Rsi];_rsi--_r11 總共30H 存放有要調(diào)試的程序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自動(dòng)跟蹤MT5 或 0只是檢測(cè)它的異常斷點(diǎn) -1,動(dòng)態(tài)調(diào)試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可以寫(xiě)數(shù)據(jù)了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;第一次運(yùn)行需要獲取程序需要的DLL信息lock and qword ptr [rax+78ffa110h],0;進(jìn)程IDlock and qword ptr [rax+78ffa120h],0;78ffa120h license.lic 文件句柄mov rcx,[rdx+_CONTEXT._R13] ;sizeof_filemov qword ptr [rax+78ffa118h],rcx;被調(diào)試程序大小mov rcx,[rdx+_CONTEXT._R14];lock and qword ptr [rax+78ffa108h],0lock or qword ptr [rax+78ffa108h],rcx;總開(kāi)關(guān),系統(tǒng)在初始化時(shí),不需要任何檢測(cè)的,我們的調(diào)試器還沒(méi)有啟動(dòng)呢!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 繼續(xù)執(zhí)行ret.endifmov rax, @NEXT_PEB_LDR_DATAmov rax,[rax].endw.endif.endif.endif.endif.endif.endif.endif;是否MT5產(chǎn)生的異常mov rax,ipmov rcx,[rax+78ffa108h] ;總開(kāi)關(guān),系統(tǒng)在初始化時(shí),不需要任何檢測(cè)了.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? ;進(jìn)程ID.if <<cmp rcx,rax>>, NOZERO?jmp exit ;不是我們要處理的程序.endif.else ;如果進(jìn)程ID為空說(shuō)明之前還沒(méi)有捕獲到MT5的異常 這里繼續(xù)在本次異常里嘗試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];;其實(shí)這里還是== 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? ; 要調(diào)試的程序名長(zhǎng)度mov rsi,[rax+_UNICODE_STRING.Buffer]mov rax,iplea rdi ,[rax+78ffa030h+8]cldrepz cmpsb.if ZERO? ;MT5的異常;這里找到MT5了;保存加載的DLL信息和進(jìn)程IDmov rax,ipmov rcx,@DllBasemov [rax+78ffa0e8h],rcxmov rcx,[rax+78ffa000h].if <<test rcx,rcx>>,ZERO? ;第一次運(yùn)行需要獲取程序需要的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可以寫(xiě)數(shù)據(jù)了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;第一次運(yùn)行需要獲取程序需要的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信息發(fā)給調(diào)試器mov @NEXT_PEB_LDR_DATA,rax; mov rax,ip; mov rcx,[rax+78ffa0f8h];;NTDLL可以寫(xiě)數(shù)據(jù)了; mov rdx,0; mov r8,0; lea rax, [rax+78e9bd70h];; call rax ;ntdll!ZwWaitForSingleObjectmov rax,ip@@:lock bts qword ptr [rax+78ffa0f8h], 0 ; BTS就是根據(jù)位偏移值從位串中取出一位放入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];我們?cè)O(shè)置的長(zhǎng)度是40h unicode模式 是ASCII碼長(zhǎng)度的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;把進(jìn)程id保存起來(lái),下次直接通過(guò)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 客戶(hù)端可以讀數(shù)據(jù)了.break ;跳出上一層循環(huán).elsejmp error.endif.elsejmp error.endif.elsejmp error.endif.else.break ;如果已經(jīng)設(shè)置好了,就不需要重復(fù)設(shè)置了.endif.endif.endifmov rax,@NEXT_PEB_LDR_DATAmov rax,[rax+LIST_ENTRY.Flink].endwmov rax,ipmov rcx,[rax+78ffa110h];進(jìn)程ID.if <<test rcx,rcx>>, ZERO?;沒(méi)有填充進(jìn)程IDjmp exit.endif.elsejmp exit.endif.elsejmp exit.endif.elsejmp exit.endif.endif;這里確定是MT5后繼續(xù)執(zhí)行mov rax,ipmov rdi,[rax+78ffa0e8h] ;mt5DllBasemov @DllBase,rdi@@:lock bts qword ptr [rax+78ffa0f8h], 0 ; BTS就是根據(jù)位偏移值從位串中取出一位放入CF中,然后將位串中的該位置成1 ;;;;NTDLL可以寫(xiě)數(shù)據(jù)事件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的地址會(huì)產(chǎn)生異常.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 已經(jīng)替換了78E681ED的地址; mov _r11,rax;pop rax;要對(duì)VEH作個(gè)檢測(cè); mov r13d,2 ;VEH: 向量化異常處理程序(進(jìn)程相關(guān)) mov r13d,3 對(duì)VCH檢測(cè); mov rax, qword ptr gs:[30h] ;teb; mov r12, [rax+60h] ;peb; mov eax, [r12+50h] ;ProcessUsingVEH; bt eax, r13d ; ;BT 把 eax 的第3位(或者 第2位根據(jù) r8+2決定)復(fù)制到 CF 從0 開(kāi)始排列; +0x050 ProcessUsingVEH : Pos 2, 1 Bit; +0x050 ProcessUsingVCH : Pos 3, 1 Bit; VEH: 向量化異常處理程序(進(jìn)程相關(guān)); VCH: 同上,也是向量化異常處理程序,; 不過(guò)它總是在最后被調(diào)用(進(jìn)程相關(guān));VEH,VCH:保存在ntdll.dll模塊的_LdrpVectorHandlerList全局變量里; .if CARRY?; .endif;0F 82 FD 16 00 00 jb loc_78E6988Dcomment ~mov rax,ipmov rcx,[rax+78ffa100h] ;1自動(dòng)跟蹤MT5 或 0只是檢測(cè)它的異常斷點(diǎn) -1,動(dòng)態(tài)調(diào)試.if <<test rcx,rcx>>, GREATER?;自動(dòng)跟蹤MT5mov rax,ipmov rsi,[rax+78ffa008h];@viewBaseAddresslea rsi,[rsi+4096+80h] ;這里存入的是官方的異常斷點(diǎn),這個(gè)值應(yīng)該是個(gè)偏移量,因?yàn)槌绦蛎看窝b入的地址應(yīng)該不一樣。;前4 個(gè)字節(jié)是異常總共占用的大小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? ;官方的斷點(diǎn)需要原程序自己去處理mov r8d,[rsi+orgbreak.except_flags][rbx];官方的斷點(diǎn)要在 RtlpCallVectoredHandlers 里標(biāo)記 還要在RtlRestoreContext里標(biāo)記mov rax,iplock and qword ptr [rax+78ffa0f0h], 0 ; release spin lock,通知seh_64 接收數(shù)據(jù)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;這里不會(huì)返回了.endifadd rbx,sizeof orgbreakdec rcx.endwmov rsi,_rdxmov rax,[rsi+ _CONTEXT._Rip]track_point::.if <<cmp byte ptr [rax],09ch>>, ZERO?;;9c pushfq 如果當(dāng)前INT1中斷的地址內(nèi)容是 pushfsub qword ptr [rsi+ _CONTEXT._Rsp],8 ;模擬pushfq 的執(zhí)行mov eax,[rsi+ _CONTEXT.EFlags]and rax,0fffffffffffffeffh ;把tf 置0 if(中斷標(biāo)志) 用sti cli 修改,用戶(hù)模式?jīng)]有權(quán)限mov rbx,[rsi+ _CONTEXT._Rsp]mov [rbx],raxinc [rsi+ _CONTEXT._Rip];模擬pushf 之后 跳過(guò)pushf 的執(zhí)行mov rax,ipmov rdi,[rax+78ffa008h];@viewBaseAddressmov qword ptr [rdi][recvfromntddd.flage_CONTEXT_EFlags],1;我們模擬pufhf 的執(zhí)行 所以加個(gè)標(biāo)志通知 seh_64。exe 處理這個(gè)情況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 ;或許有多個(gè)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 之后 跳過(guò)pushf 的執(zhí)行mov rax,[rsi+ _CONTEXT._Rip]jmp track_point.elseif <<cmp word ptr [rax],09c2eh>>, ZERO?;;9cinc [rsi+ _CONTEXT._Rip];模擬pushf 之后 跳過(guò)pushf 的執(zhí)行mov rax,[rsi+ _CONTEXT._Rip]jmp track_point.elseif <<cmp word ptr [rax],09c40h>>, ZERO?;;9cinc [rsi+ _CONTEXT._Rip];模擬pushf 之后 跳過(guò)pushf 的執(zhí)行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 接收數(shù)據(jù) release spin lock,通知seh_64 接收數(shù)據(jù) release spin lock,通知seh_64 接收數(shù)據(jù)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 繼續(xù)執(zhí)行 我們HOOK的 RtlRestoreContext 會(huì)設(shè)置單步ret ;返回后繼續(xù)調(diào)用RtlRestoreContext 這個(gè)RtlRestoreContext 調(diào)用不會(huì)再產(chǎn)生 異常,(我們沒(méi)有設(shè)置 單步標(biāo)志)下一次的異常是在返回用戶(hù)地址后產(chǎn)生的.elseif <<test rcx,rcx>>, zero? ;1要調(diào)試MT5 或 0只是檢測(cè)它的異常斷點(diǎn) -1,動(dòng)態(tài)調(diào)試mov rax,iplock and qword ptr [rax+78ffa0f0h], 0 ; release spin lock,通知seh_64 接收數(shù)據(jù).elsemov rax,iplock and qword ptr [rax+78ffa0f0h], 0 ; release spin lock,通知seh_64 接收數(shù)據(jù) release spin lock,通知seh_64 接收數(shù)據(jù) release spin lock,通知seh_64 接收數(shù)據(jù)_80h_instruct:mov rax,ip@@:lock bts qword ptr [rax+78ffa0f8h], 0 ; BTS就是根據(jù)位偏移值從位串中取出一位放入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單步調(diào)試指令區(qū) sizeof == 80h.if <<cmp byte ptr [rsi],0>>,NOZERO? ;這里是指令區(qū)lea rdi,[rax+78ffa060h]mov rcx,10hrep movsq ;讀80h個(gè)指令mov rcx,_rcxmov rdx,_rdxlea rbx,[rax+78ffa060h]call rbx;qword ptr [rax+78ffa060h] ;80H字節(jié)的指令區(qū)mov rax,iplock and qword ptr [rax+78ffa0f0h], 0 ; release spin lock,通知seh_64 接收數(shù)據(jù) release spin lock,通知seh_64 接收數(shù)據(jù) release spin lock,通知seh_64 接收數(shù)據(jù)jmp _80h_instructnop.elsemov rax,iplock and qword ptr [rax+78ffa0f0h], 0 ; release spin lock,通知seh_64 接收數(shù)據(jù) release spin lock,通知seh_64 接收數(shù)據(jù) release spin lock,通知seh_64 接收數(shù)據(jù).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 繼續(xù)執(zhí)行; ret ;不能直接返回:RtlRestoreContext 已經(jīng)被我們HOOK,會(huì)生成單步中斷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 已經(jīng)替換了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 會(huì)破壞堆棧平衡ret_DispatchException endp

以上就是關(guān)于pos機(jī)開(kāi)機(jī)異常,NTDLL 異常處理在調(diào)試中的應(yīng)用的知識(shí),后面我們會(huì)繼續(xù)為大家整理關(guān)于pos機(jī)開(kāi)機(jī)異常的知識(shí),希望能夠幫助到大家!

轉(zhuǎn)發(fā)請(qǐng)帶上網(wǎng)址:http://www.shbwcl.net/newstwo/102299.html

你可能會(huì)喜歡:

版權(quán)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶(hù)自發(fā)貢獻(xiàn),該文觀點(diǎn)僅代表作者本人。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如發(fā)現(xiàn)本站有涉嫌抄襲侵權(quán)/違法違規(guī)的內(nèi)容, 請(qǐng)發(fā)送郵件至 babsan@163.com 舉報(bào),一經(jīng)查實(shí),本站將立刻刪除。