先
祝各位 在鼠年喜气洋洋,满面阳光灿烂,爱情扬眉吐气,事业洋洋得意,晦气扬长而去,万事阳关大道!
鼠属鼠,财源“鼠”不胜数
人喜盛世;鼠兆丰年
"鼠"不尽的快乐!
"鼠"不尽的收获!
"鼠"不尽的钞票!
"鼠"不尽的笑容!
"鼠"不尽的幸福!
"鼠"不尽的朋友!
"鼠"不尽的喜气!
"鼠"不尽的财富!
"鼠"不尽的甜蜜!
"鼠"不尽的激情!
"鼠"不尽的活力!
"鼠"不尽的健康!
"鼠"不尽的荣誉!
祝贺词由lin版提供,大家不要忘记祝贺lin版阿:)
文章已经写过2篇了,也和大家学习了一些知识,先做1点点小小个人声明
1.偶不是做游戏的,也不是做外挂的,研究NP没有什么商业目的,也许一些人不信
不过,可以想想,我写这些东西出来只会使NP保护加难,不会有任何好处
写文章其实是个学习的过程,我写的时候发现很多东西不懂,又得去查询资料
写代码的时候是直接拿windbg出来的硬编码hook,当然不能通用
为了写文章可以学习到很多知识,这也是偶写出来的原因了
2.为啥要分析NP? 这个,其实很简单,玩驱动总想拿点东西来分析1下
正如玩壳的喜欢找点东西来拆了分析一样,为啥偶选择了NP呢,因为没有
选择了阿, 如果偶把卡巴主动防御驱动部分一个一个拆开分析,岂不会
得到个做病毒的称号?更有可能指责偶成了谋害广大网民了,所以,哈哈.
分析NP最多就说偶是做挂了,不可能"谋害":lol 反正从技术本质上都是
hook unhook checkhook一类的东西
3.NP有一些小把戏,比如隐藏进程什么的,记住是断开链表就ok了
我们去搜索eprocess,自己恢复链表,具体代码很简单
,偶从开始分析NP直到实现挂od飞np,一共5天,比起forgot大侠2天
来说是慢多了,不过还好,实现了目标,也就是所谓的,forgot大侠说的
加入CUG的必须会挂od飞np:handshake
4.其实NP很多大牛已经给了我们很多提示,比如阿莫西林同学,
那张图片不知道大家看过没有,偶是仔细看了的,还算不错
按照那个方法是可以的,相信你自己,偶一个菜鸟花了5天
你应该比偶聪明,参考一些代码,3-4天应该没问题了吧
5.正因为偶不是做外挂的,所以偶不关心游戏本身,偶的文章尽力避开
直接提到游戏,正如我们研究加壳保护尽力不提及目标软件一样,断开np
以后游戏是否会掉线?会异常?偶不关心,偶的目的就是od能够直接进入np进程了
即可,
6.听说最新更新np添加了1个什么主动防御打分机制?没有仔细看了,不过也不是什么
难事情,关键还是一个理念问题,思路的灵巧,还有方法的多变,代码不是最重要的
明白了理念,其实代码很好写
7.总结1下那篇没有完成的小说吧,其实也不可能完成
至于NP和HS谁厉害?仁者见仁智者见智吧,不过偶猜测2个一起运行没有问题
不过偶没有做实验.因为偶的虚拟机跑不起;开2个游戏直接死机
哪位大侠有兴趣可以试试.
8.下面还要说什么?偶的id?声明1下 不是外挂的意思
大家记住 猪娃哥,就行了,意思就是喂猪的:lol
9.貌似又灌水了很多,恩,最后还有1个东西,HS的int3挂钩
之前先提及1下一些NP的邪恶东西,还有一些关kerneldebuger
监控0x60 64之类的,不多说了,因为偶也没有仔细测试
只说0x60 64发个特殊电位可以直接给你重启
原因就是改变reset电位,键盘控制器可以直接改变reset电位,就像你按下
机箱上的reset一样的效果,没有任何过程的直接重启
先注意1下,下面东西又是很难的了..:loveliness:
什么是中断?中断和异常(exception) 中断向量
"中断被定义为当一个事件发生时,改变处理器的指令序列。这样的事件可由CPU芯片
内部或者外部硬件产生电信号产生"
Intel参考手册上指出“同步中断”(在一个指令执行完成后,由CPU控制单元产生的)作为“异常”。
异步中断(可能会在任意时刻由其他硬件产生的)才称为“中断”。中断被外部的I/O设备产生。
但是异常是由编程错误或者是由反常情况(必须由内核来处理)触发的。在该文档中,
术语“中断信号”既指异常又指中断。
中断分为两种类型:可屏蔽中断--它在短时间片段里可被忽略;不可屏蔽中断--它必须被立即处理。
不可屏蔽中断是由紧急事件产生例如硬件失败。著名的IRQS(中断请求)失败划为可屏蔽中断。
异常被分为不同的两类:处理器产生的异常(Faults, Traps, Aborts)和编程安排的
异常(用汇编指令int or int3 触发)。后一种就是我们经常说到的软中断
后面那个就是int3 int3就是CC,也就是我们的bp断点.
什么是IDT?
IDT = Interrupt Descriptor Table 中断描述表
IDT是一个有256个入口的线形表,每个中断向量关联了一个中断处理过程。
每个IDT的入口是个8字节的描述符,所以整个IDT表的大小为256*8=2048 bytes
IDT有三种不同的描述符或者说是入口:
- 任务门描述符 Task Gate Descriptor
- 陷阱门描述符 Trap Gate Descriptor
- DPL=Descriptor Privilege Level
不详细说了,我们看看r0cmd
介绍下r0cmd(不知道有没有类似的工具,有还请告知):
r0cmd 就是ring0下读写内存的工具,主要是用来查看修改IDT,SST及相关只能在
ring0下才能访问的内存,例如driver的内存空间,这个很重要,破解需要修改driver.
使用前一定要把它的驱动文件放到system32\drivers目录中,r0cmd的主要命令:
1. 读IDT表: r0cmd /viewidt:idt.txt 文本方式读出,用于查看;
2. 读IDT表: r0cmd /dumpidt:idt.bin hex方式读出,用于保存;
3. 写IDT表: r0cmd /loadidt:idt.bin 用于恢复IDT表;
4. 读SST表: r0cmd /dumpsst_nt:sst.bin hex方式读出,用于保存;
5. 写SST表: r0cmd /loadsst_nt:sst.bin 用于恢复;
6. 读内存: r0cmd /dump raw.bin FABC000 1000 (文件/地址/长度)用于dump内存分析;
7. 写内存: r0cmd /load raw.bin FABC000 1 (写内存一般不宜写太多,错误会造成boot) MJ0011--HackShield同冰刃存在冲突,问题是KERNEL_MODE_EXCEPTION_NOT_HANDLED,异常号是0x80000004(STATUS_SINGLE_STEP),引发错误的地址在hal的一个函数READ_PROT_UCHAR中,经过分析,出错当时DR7被enable,开启了读写断点,DR2的值是0x60,即是HackShield会在0x60号端口上下IO硬件断点,而!idt -a 查看IDT,int 1 & int3号中断的处理例程都是在系统原始的KiTrap01 & KiTrap03上,所以当READ_PORT_UCHAR执行了in al ,dx 后,就会发生异常下来,而int 1 & 3中处理例程没有被修改,因此直接发生异常,BSOD了,进一步查看原因, Icesword会不断重写int 1 & int3为系统原始的KiTrap*的地址,因此当HackShield修改了int 3的处理例程,然后设下硬件断点后,冰刃恢复了int 3的处理例程,一但再有键盘/鼠标的中断过来,触发了i8042中的处理例程调用hal中函数读写0x60号端口(键盘/鼠标的input/output buffer端口),就会被断下来,而int 3已经被恢复,因此当掉
幻影,不知道还有人记得吗?幻影最大的特点可谓是其反跟踪了,幻影的Anti能力之强在 Xtreme-Protector未出之前是首屈一指的。正如 CoDe_inJect 大侠所言:“这个壳在国内如日中天,奥妙在于哪里?就在于 anti做得比较完善,它是我见到的最早使用驱动的壳,虽然驱动的运用仅仅是为了在NT下切到Ring0,但他开创了壳使用驱动的先例。对idt进行修改,改变了int 1 and int 3的地址。”
理论部分完毕,我们知道int3会发生1个异常,异常处理流程很复杂,..但是会进入中断.
IDT hook是这样做的
NTSTATUS AddInterrupt()
{
PIdtEntry_t IdtEntry;
/* Get the Base and Limit of IDTR Register */
_asm sidt buffer
IdtEntry=(PIdtEntry_t)Idtr->Base;
/* Save away the old IDT entry */
memcpy(&OldIdtEntry, &IdtEntry[ADDINT], sizeof(OldIdtEntry));
_asm cli
/* Initialize the IDT entry according to the interrupt gate requirement */
IdtEntry[ADDINT].OffsetLow=(unsigned short)InterruptHandler;
IdtEntry[ADDINT].Selector=8;
IdtEntry[ADDINT].Reserved=0;
IdtEntry[ADDINT].Type=0xE;
IdtEntry[ADDINT].Always0=0;
IdtEntry[ADDINT].Dpl=3;
IdtEntry[ADDINT].Present=1;
IdtEntry[ADDINT].OffsetHigh=(unsigned short)((unsigned int)InterruptHandler>>16);
_asm sti
return STATUS_SUCCESS;
}
void RemoveInterrupt()
{
PIdtEntry_t IdtEntry;
/* Reach to IDT */
IdtEntry=(PIdtEntry_t)Idtr->Base;
_asm cli
/* Restore the old IdtEntry */
memcpy(&IdtEntry[ADDINT], &OldIdtEntry, sizeof(OldIdtEntry));
_asm sti
}
void __declspec (naked) InterruptHandler()
{
_asm
{
PUSHAD
PUSHFD
PUSH FS
MOV EBX,00000030h
MOV FS,BX
SUB ESP, 50h
MOV EBP,ESP
;Setup the exception frame to NULL
MOV EBX,DWORD PTR CS:[0FFDFF000h]
MOV DWORD PTR DS:[0FFDFF000h], 0FFFFFFFFh
MOV DWORD PTR [EBP],EBX
;Save away the existing KSS EBP
MOV ESI, DWORD PTR CS:[0FFDFF124h]
MOV EBX,DWORD PTR [ESI+00000128h]
MOV DWORD PTR [EBP+4h],EBX
MOV DWORD PTR [ESI+00000128h],EBP
;Save away the thread mode (kernel/user)
MOV EDI,DWORD PTR [ESI+00000134h]
MOV DWORD PTR [EBP+8h],EDI
;Set the thread mode (kernel/user) based on the code selector
MOV EBX,DWORD PTR [EBP+7Ch]
AND EBX,01
MOV BYTE PTR [ESI+00000134h],BL
STI
}
DbgPrint("%S:Test Call\n",DRIVER_DEVICE_NAME);
_asm
{
MOV ESI,DWORD PTR CS:[0FFDFF124h]
MOV EBX,DWORD PTR [EBP+4]
MOV DWORD PTR [ESI+00000128h],EBX
;Restore the exception frame
MOV EBX,DWORD PTR [EBP]
MOV DWORD PTR FS:[00000000],EBX
;Restore the thread mode
MOV EBX,DWORD PTR [EBP+8h]
MOV ESI,DWORD PTR FS:[00000124h]
MOV BYTE PTR [ESI+00000134h],BL
ADD ESP, 50h
POP FS
POPFD
POPAD
}
_asm iretd
}
看起来很复杂,其实没有什么,就是替换 替换 替换阿
把你自己的异常处理函数换掉系统的异常处理函数.恢复起来很简单,无非就是先保存系统的函数而已
但是不要忘记HS的监视,我们需要1些特殊手段做掉HS
当然也可以做掉NP的监视线程
我们可以直接结束线程,但是更好的手段是断开线程调度链表
线程调度链表--系统CPU时间分片给每个线程,线程要执行就必须要调度,我们安静的把邪恶线程
给去掉,邪恶线程虽然还在,但是永远没有机会运行.哈哈,我们可以做自己想干的事情了:smoke
一些代码偶也没有完成,就没办法提供了
参考PHRACK一些资料,个人感觉PHRACK虽然是hack期刊,听说最近重新开了
但是有很多内核知识很不错
感谢各位看到这里,再次祝福新年快乐
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课