windows驱动逆向(windows驱动教程)

怎么更改windows的设备驱动

1、右键桌面上的“计算机”,属性。

2、选择左边选项卡的“高级系统设置”

3、切换到左边的“硬件”选项卡,选择第二个“设备安装设置”

4、在弹出来的窗口选择“否” 第三项,从不安装即可!

驱动的安装与逆向

对于一个经常写程序的人来说,写驱动不是一件困难的事情。因为网络上有很多现成的

代码,要实现某个功能,直接 Ctrl+C和Ctrl+V 就能解决问题。但是写出来了驱动能不能加

载进入内核就是另外一回事了,准确的说是能不能存在于别人的硬盘上就是另外一回事了。

因为很多杀毒软件(特别像360这种没技术含量的)见到后缀名为sys的文件就直接删除,

甚至连调用NtLoadDriver的机会都没有。对于一般的软件来说,给出一个声明说明一下解

决方法就算了。但是对于恶意程序,是不能给出声明的。于是很多恶意软件的作者另辟蹊径,

利用大公司写好的而且有数字签名的驱动来做坏事。

有人说,大公司做好的驱动怎么可能被用来做坏事呢?其实,这是很容易理解的事情。

很多安全类或者系统优化类的软件,甚至系统毫不相关的软件(比如:迅雷)都附带有驱动。

这些驱动都带有一定的通用性。q_lai_a_qu网友在其博客里说:“ComputerZ.sys……没事

逆了逆是鲁大师的驱动,发现这个驱动功能齐全,而且没有调用者验证!既可以读、写Msr

寄存器,也可以用in、out指令读写端口,而且char/short/long数据长度齐全!”。这个是

个人之言,可信度请自行揣度。下面说个可信度比较高的例子:曾经有病毒利用了360的

AntiRK.dll来删除杀毒软件的文件(请自行用谷歌搜索“360 antirk.dll”,会有惊喜发现。

AntiRK.dll虽然不是驱动,但也是被非法利用了)。破坏杀毒软件的病毒已经算是小儿科了,

其实利用某些驱动还能破坏硬件!我最近在笔记本上折腾硬件,“本友会”上的网友给我推

荐了几款软件:SetFSB、ThrottleStop、NvFlash、WinFlash。它们分别是修改CPU外频、设

置CPU倍频(可以调节CPU电压)、读写显卡BIOS和读写主板BIOS的软件。一言概括他们的特性,

就是它们都支持NT x86/x64,它们的驱动都有正规数字签名(特别是最后两个,分别带的是 NVIDIA和ASUS的数字签名)。

最为重要的是,他们的驱动没有加花加壳,没有校验调用者,

如果利用这几个驱动,加上一丁点的逆向知识,就能做出破坏性的病毒(以下摘自我在紫水

晶编程论坛的帖子):

1.SetFSB能调节处理器的外频,如果直接把外频调到600MHz,电脑会瞬间黑屏,可能

会损坏 CPU或主板;

2.ThrottleStop能调节 CPU的倍频(如果CPU没有锁倍频),如果直接把倍频调到 31,

电脑会瞬间黑屏,可能会损坏CPU 或主板;ThrottleStop还能调节CPU的核心电压,如果

把CPU的核心电压调到3V,能直接烧毁CPU 甚至主板;

3.NvFlash、WinFlash等软件能直接读写BIOS(显卡BIOS 和主板BIOS),我们可以把

BIOS全部写零;

4.如果做病毒的话,先写坏显卡BIOS 和主板BIOS,然后通过调节电压烧掉显卡和CPU

(有可能会连同主板一起损坏);

解决方案

由此可见,没有验证调用者的驱动实在是有着巨大的危害。我最近受学院委托,做一个

需要驱动的软件(那个驱动会被加上数字签名)。为了防止上述悲剧发生,我决定在正式写

驱动之前,先解决如何防止自己的驱动被恶意利用。以前我曾经在紫水晶编程论坛上问过这

个问题,网友的回答五花八门,不过大概是可以分成三类:第一类是信息验证,比如应用程

序发个信息给驱动来验证一下是“自己人”;第二类是加壳保护,比如给驱动和应用程序加

上极强难脱的壳,利用VMP加密通信部分(类似XueTr 的做法);还有人提出混合应用,综

合第一类和第二类的做法。

这三种想法看似都不错,但是我认为不妥。第一种:别人只要把驱动全部逆向完毕就行

了;第二种:虽然VMP保护和加保护壳使得破解不容易,但是不是使破解变得不可能。而且

VMP 和保护壳能使程序执行的效率降低,我不太喜欢。最可恶的是,杀毒软件对加了壳(甚

至包括 UPX)和 VMP的程序一律报毒,得不偿失。于是我想出了第三种思路:校验调用者的

特征。如果符合,就执行功能语句,否则不予执行。如何校验调用者的特征码呢?不少人想

到的是使用CRC32 或者 MD5。使用它们不是不可以,不过我还有自己的想法。我的想法是自

己设计一套验证算法,它的规则如下:

1.获得调用者的EPROCESS

2.通过调用者的EPROCESS获得调用者的文件路径

3.获取调用者的文件全部内容,放到字节数组buff里

4.把 buff里所有的元素依次相加减(fb1 + fb2 - fb3...),得到y1

5.把 buff里所有的元素依次异或(0 XOR fb1 XOR fb2 XOR fb3...),得到y2

把 y1和 y2与已经计算出来的数值对比,如果都相同则执行功能代码,如果不相同则不

执行功能代码

获得调用者的EPROCESS直接用 PsGetCurrentProcess()就行了,获得调用者的文件路

径比较麻烦,大家可以使用我以前向高手购买的代码(已经封装为函数,方便调用):

//依据 EPROCESS得到进程全路径

VOID GetFullPathByEprocess( ULONG eprocess, PCHAR ProcessImageName )

{

ULONG object;

PFILE_OBJECT FileObject;

UNICODE_STRING FilePath;

UNICODE_STRING DosName;

STRING AnsiString;

FileObject = NULL;

FilePath.Buffer = NULL;

FilePath.Length = 0;

*ProcessImageName = 0;

//Eprocess-sectionobject(offset_SectionObject)

if(MmIsAddressValid((PULONG)(eprocess+offset_SectionObject)))

{

object=(*(PULONG)(eprocess+offset_SectionObject));

//KdPrint((\"[GetProcessFileName] sectionobject :0x%x\\n\",object));

if(MmIsAddressValid((PULONG)((ULONG)object+0x014)))

{

object=*(PULONG)((ULONG)object+0x014);

//KdPrint((\"[GetProcessFileName] Segment :0x%x\\n\",object));

if(MmIsAddressValid((PULONG)((ULONG)object+0x0)))

{

object=*(PULONG)((ULONG_PTR)object+0x0);

//KdPrint((\"[GetProcessFileName]

ControlAera :0x%x\\n\",object));

if(MmIsAddressValid((PULONG)((ULONG)object+0x024)))

{

object=*(PULONG)((ULONG)object+0x024);

if (NtBuildNumber = 6000) object=((ULONG)object

0xfffffff8);

//KdPrint((\"[GetProcessFileName]

FilePointer :0x%x\\n\",object));

}

else

return ;

}

else

return ;

}

else

return ;

}

else

return ;

FileObject=(PFILE_OBJECT)object;

FilePath.Buffer = ExAllocatePool(PagedPool,0x200);

FilePath.MaximumLength = 0x200;

//KdPrint((\"[GetProcessFileName]

FilePointer :%wZ\\n\",FilePointer-FileName));

ObReferenceObjectByPointer((PVOID)FileObject,0,NULL,KernelMode);

RtlVolumeDeviceToDosName(FileObject- DeviceObject, DosName);

RtlCopyUnicodeString(FilePath, DosName);

RtlAppendUnicodeStringToString(FilePath, FileObject-FileName);

ObDereferenceObject(FileObject);

RtlUnicodeStringToAnsiString(AnsiString, FilePath, TRUE);

if ( AnsiString.Length = 216 )

{

memcpy(ProcessImageName, AnsiString.Buffer, 0x100u);

*(ProcessImageName + 215) = 0;

}

else

{

memcpy(ProcessImageName, AnsiString.Buffer, AnsiString.Length);

ProcessImageName[AnsiString.Length] = 0;

}

RtlFreeAnsiString(AnsiString);

ExFreePool(DosName.Buffer);

ExFreePool(FilePath.Buffer);

}

以上代码需要三个硬编码,分别是NtBuildNumber(系统版本号)、EPROCESS中的

SectionObject项和UniqueProcessId项的偏移。我测试的操作系统是Windows 2003。所以

我在代码里如下定义:

#define offset_SectionObject 0x124

#define offset_UniqueProcessId 0x94

ULONG NtBuildNumber=3790;

获得进程路径后就校验特征码。由于流程已经说清楚了,所以直接给出代码:

VOID CalcChar(PUNICODE_STRING logFileUnicodeString, LONG *XorChar, LONG

*AnSChar)

{

OBJECT_ATTRIBUTES objectAttributes;

IO_STATUS_BLOCK iostatus;

HANDLE hfile;

NTSTATUS ntStatus;

FILE_STANDARD_INFORMATION fsi;

PUCHAR pBuffer;

ULONG i=0,y1=0,y2=0;

//初始化 objectAttributes

InitializeObjectAttributes(objectAttributes,

logFileUnicodeString,

OBJ_CASE_INSENSITIVE,//对大小写敏感

NULL,

NULL);

//创建文件

ntStatus = ZwCreateFile(hfile,

GENERIC_READ,

objectAttributes,

iostatus,

NULL,

FILE_ATTRIBUTE_NORMAL,

FILE_SHARE_READ,

FILE_OPEN,//即使存在该文件,也创建

FILE_SYNCHRONOUS_IO_NONALERT,

NULL,

0 );

if (!NT_SUCCESS(ntStatus))

{

dprintf(\"The file is not exist!\\n\");

return;

}

//读取文件长度

ntStatus = ZwQueryInformationFile(hfile,

iostatus,

fsi,

sizeof(FILE_STANDARD_INFORMATION),

FileStandardInformation);

dprintf(\"The program want to read %d bytes\\n\",fsi.EndOfFile.QuadPart);

//为读取的文件分配缓冲区

pBuffer = (PUCHAR)ExAllocatePool(PagedPool,

(LONG)fsi.EndOfFile.QuadPart);

//读取文件

ZwReadFile(hfile,NULL,

NULL,NULL,

iostatus,

pBuffer,

(LONG)fsi.EndOfFile.QuadPart,

NULL,NULL);

dprintf(\"The program really read %d bytes\\n\",iostatus.Information);

//异或计算

for(i=0;iiostatus.Information;i++)

y1=y1^(LONG)(*(pBuffer+i));

*XorChar=y1;

//加减计算

for(i=0;iiostatus.Information;i++)

{

if(i%2==0)

y2=y2+(LONG)(*(pBuffer+i));

else

y2=y2-(LONG)(*(pBuffer+i));

}

*AnSChar=y2;

//关闭文件句柄

ZwClose(hfile);

//释放缓冲区

ExFreePool(pBuffer);

}

接下来就要调用了。我们需要编写一个函数VerifyCaller,在此函数里有两个值需要

固化在驱动里,就是合法调用者的两个特征值。为了方便计算这两个特征值,我特地写了个

应用程序,核心代码如下:

Option Explicit

Private Function ReadFile(ByVal strFileName As String, Optional ByVal

lngStartPos As Long = 1, Optional ByVallngFileSize As Long = -1) As Byte()

Dim FilNum As Long

FilNum = FreeFile

Open strFileName For Binary As #FilNum

If lngFileSize = -1 Then

ReDim ReadFile(LOF(FilNum) - lngStartPos)

Else

ReDim ReadFile(lngFileSize - 1)

End If

Get #FilNum, lngStartPos, ReadFile

Close #FilNum

End Function

Private Function WriteFile(ByVal strFileName As String, bytData() As Byte,

Optional ByVal lngStartPos As Long = -1,Optional ByVal OverWrite As Boolean =

True)

On Error GoTo erx

Dim FilNum As Long

FilNum = FreeFile

If OverWrite = True And Dir(strFileName) \"\" Then

Kill strFileName

End If

Open strFileName For Binary As #FilNum

If lngStartPos = -1 Then

Put #FilNum, LOF(FilNum) + 1, bytData

Else

Put #FilNum, lngStartPos, bytData

End If

Close #FilNum

erx:

End Function

Private Sub Command1_Click()

Dim buff() As Byte, i As Long, y As Long, ub As Long

\'text1.text is the file name

buff = ReadFile(Text1.Text, 1, -1)

ub = UBound(buff)

\'calc xor char

y = 0

For i = 0 To ub

y = y Xor buff(i)

Next

Text2.Text = CLng(y)

DoEvents

\'calc add/sub char

y = 0

For i = 0 To ub

If i Mod 2 = 0 Then

y = y + CLng(buff(i))

Else

y = y - CLng(buff(i))

End If

Next

Text3.Text = CLng(y)

End Sub

Private Sub Form_Load()

Me.Icon = LoadPicture(\"\")

End Sub

驱动里的 VerifyCaller代码如下:

LONG VerifyCaller(void)

{

PEPROCESS cur_ep;

char cur_pp[260];

char *nt_cur_pp;

ANSI_STRING asCur_pp;

UNICODE_STRING usCur_pp;

LONG xorc, ansc;

cur_ep=PsGetCurrentProcess();

GetFullPathByEprocess((ULONG)cur_ep, cur_pp);

//在文件名前面加上\\??\\

nt_cur_pp=cs(\"\\\\??\\\\\",cur_pp);

DbgPrint(\"%s\",nt_cur_pp);

RtlInitAnsiString(asCur_pp, nt_cur_pp);

RtlAnsiStringToUnicodeString(usCur_pp, asCur_pp, TRUE);

DbgPrint(\"%wZ\",usCur_pp);

CalcChar(usCur_pp, xorc, ansc);

DbgPrint(\"XorChar: %ld; AnSChar: %ld\",xorc,ansc);

//这个就是事先算好的合法程序的特征码,【必须】固化在驱动里!

if(xorc==186 ansc==136176)

return 1;

else

return 0;

}

在 DispatchIoctl函数的每个功能执行之前,都调用VerifyCaller()校验一下调用者:

switch(uIoControlCode)

{

case IOCTL_VERIFY:

{

DbgPrint(\"[MyDriver] DispatchIoctl - IOCTL_VERIFY\");

if(VerifyCaller()==1)

DbgPrint(\"[MyDriver] {IOCTL_VERIFY} Function code run now!\");

else

DbgPrint(\"[MyDriver] {IOCTL_VERIFY} You\'re illegal caller!\");

status = STATUS_SUCCESS;

break;

}

//下面省略

}

运行测试

3.首先把合法的调用者,非法的调用者(用eXeScope随便把合法的调用者Patch一下,

比如删掉程序的版本信息)和驱动复制到虚拟机

4.用合法的调用者来加载驱动并执行

5.用非法的调用者来加载驱动并执行

6.对比以上两者在DbgView的输出

调用者合法时:

调用者非法时:

写在最后

写完这篇文章,我必须再次重申:只有当驱动程序携带正式数字签名时,验证调用者的

代码才有使用价值。为什么这么说呢?因为别人无法patch 带有正式数字签名的驱动(一旦

驱动被 patch,签名就失效了,就像被破处的女人,不值钱了。这个比喻虽然粗俗,但是很

恰当)。而没有加上签名的驱动,本来就没有使用价值。即使别人要使用,直接把驱动扔到

IDA 里,什么代码都出来了。

反汇编逆向难学吗,入门难吗?

反汇编是工具来做的,比如IDA,OD,你说的这个应该是逆向和破解技术。

逆向其实是有它的难度在里面的,要跟汇编打交道,很多时候破解要涉及加密算法,驱动保护还有壳。可以这么说,逆向技术本身不算太难,但是难的是逆向防御技术。

因为逆向在windows平台上的通用性而且不是太难学,导致了商业软件为了追求安全性,产生了很多逆向分析的对抗技术,来增强自己的安全性。毕竟自己辛辛苦苦花钱花时间搞出来的东西,被别人两下学了去,怎么想怎么不舒服。

这里面,加壳鄙人不了解,不做评论。驱动保护就是在内核里搞风搞雨,入手的门槛还是比较高的。所以学逆向不难,花时间花功夫多练手。但是想把你高超的逆向功力应用到实际的商业产品上,驱动和壳是你必须面对的东西,去研究这两者会花费大量精力。

AGP论坛站长,反游戏保护和windows内核技术大牛A总听说是高二就开始研究内核技术了,lz如果花时间,也是能学成的,毕竟有成功案例在了。有点基础想撸驱动,还可以找A总报名参加下付费培训。。。广告已打, 心满意足。

逆向,反病毒,驱动开发,一些问题。

其实目前中国的软件行业很浮肿……

大量的软件公司都在做外包,而外包程序员无非就是高级打字员……

真正中国自主开发的软件并不多,能做好做大的就更少了~

前景来看,驱动开发和逆向工程都是很辛苦但也是收入颇丰的~

而且目前来看国内这方面的人才都很紧俏~

所以如果能在学校期间熟悉这两门技术之一,

对于以后就业直接走进国内一线软件公司或者大的外企

都是一个有力的筹码

逆向和驱动如果结合起来,就是内核调试

而逆向和你学的.NET平台结合起来,则是.NET逆向

都属于更为稀缺和抢手的技术!

而你说的反病毒,如果是病毒分析,其实只是逆向的一个初步。

如果你能深入的学习逆向,那病毒分析就如砍瓜切菜一般容易~

而再加上正想的驱动开发技术,那开发属于自己的杀毒软件或是HIPS也绝非难事~

这样想来,你说就业前景还会差么?

但是话说回来,真的很难。

我现在还没接触到内核,还在摸索阶段

望你早日成功吧~

windows 系统驱动安装原理

1、Windows 7系统的设备驱动文件解读

在Windows7系统中包含了一个覆盖范围很广的身边驱动程序库。在该操作系统的基本安装中,这些驱动程序都会保存在驱动程序存储区中,它们位于%SystemRoot%\System32\DriverStore\FileRepository目录下。另外,在DriverStore文件夹中还保存了对应本地化后的驱动程序信息的子文件夹,对于在系统上配置的每个语种,在这里都有一个对于的子文件夹。例如,笔者安装的是Windows7系统的英文版,有关本地化的英语驱动程序信息就位于en-us子文件夹中。

在驱动程序存储区中,每个设备驱动程序都经过了认证,并确保可以与Windows7系统之家完全兼容,通过还带有微软的数字签名,这可以确保驱动程序在操作系统中绝对可用。在安装新的兼容性即插即用设备时,Windows7系统会在驱动程序存储区中检查可用的兼容设备驱动程序。如果找到,则操作系统就会自动安装该设备。

2、应当重视的Windows 7系统设备驱动签名信息

对于Windows7系统来说,能否对周边设备提供良好的支持是其面临的严峻挑战。毫无例外地,为了保证系统的稳定性及设备的良好运行,微软建议用户选择包含数字签名是设备驱动程序版本。这对于用户来说非常重要,因为Windows7系统毕竟是目前最新系统平台之一,各方面有待于进一步的检验或者考验,而这一般为不少用户所忽略。带有微软数字签名的设备驱动程序不会让系统崩溃或者变得不稳定,同时带有微软数字签名还可以确保设备驱动程序未被篡改,这能够杜绝驱动级木马危害系统。

反之,如果用户强制使用没有数字签名的驱动程序,则很有可能导致Windows7系统的不响应或者崩溃,这甚至比在操作系统上安装普通程序导致的问题更加严重。笔者曾经有这样的体验,另外论坛中这样的因为驱动造成Windows7崩溃的案例也非常多。因此,对于Windows7系统用户来说建议尽量使用经过签名的驱动程序。当然,在某些情况下,我们可能会发现特定是设备不包含签名的驱动程序。此时,建议大家在设备制造商是网站上搜索是否有可用的带有签名的驱动程序。因为有时可能有带有签名的驱动程序,但并没有包含到设备的的驱动光盘之家或者Windows7系统的安装盘中。

3、Windows 7系统驱动文件排错

当硬件的驱动安装错误后,不仅不能够驱动该设备,而且会有可能造成深度系统的不稳定甚至崩溃。Windows7系统内置的硬件诊断功能可以检测各种类型的硬件设备故障,从而据此可进行驱动文件的排错。通常情况下,最新系统下载安装后如果系统检测到问题,那么我们将会看到一个问题报告和解决方案提示的气泡通知。单击该气泡通知即可打开问题报告和解决方案控制台。另外,我们也可以在Windows7系统的控制面板中单击“系统和维护”链接,并单击“问题报告和解决方案”打开该控制台。在问题报告和解决方案窗口中,单击“查看问题以检查”链接以查看现有的问题,或单击“检查解决方案”链接,从微软网站上搜索已知问题的可能解决方案。

4、设备驱动造成的资源冲突排错

有的时候,当我们在Windows7系统中安装了某设备的驱动文件后会显示资源冲突,那如何进行排错呢?Windows7系统的智能特性让我们进行这方面的排错非常容易。如果怀疑是某设备造成了资源冲突,可在Windows7系统的设备管理器中,单击“查看”菜单选择其中的“依类型排序资源”或“依连接排序资源”视图,即可快速查看资源的分配,在此我们可以看到ISA和PCI设备使用IRQ的情况。一般情况下每个ISA设备都有独立的IRQ设置,而多个PCI设备共享相同的IRQ设置。笔者特别提示,如果某些设备显示警告图标,同时还有感叹号,这并不是资源冲突,应该是设备配置错误。

需要注意的是,在Windows系统中,设备可以共享IRQ设置,因此两个不相关当共用了同样内存地址或I/Q端口的设备,这些设备之间通常存在冲突。确定了资源冲突的双方,我们就可以在设备管理器中手动修改某些设备的资源设置。打开该设备是属性对话框,在“资源”选项卡中选择需要使用的资源类型。如果可以更改,那么就可以取消对“使用自动设置”的选择,然后查看设置基于下拉列表中是否提供候补的配置,如果有选择该项即可解决冲突。

安卓逆向和windows逆向哪个好找工作

首先,逆向分析是一门技术,也是一门艺术。

其次,安卓逆向同样可细分为应用层APK逆向、安卓设备框架、内核驱动等逆向、基于安卓的硬件产品逆向等。此处假定楼主说的是第一种逆向。

应用层的逆向分析根据需求的不同,又可细分成APK流程逆向与功能逆向。

流程逆向通常是指简单的对APK运行流程进行分析,此类分析通常可以使用将APK置于沙盒环境中运行捕捉并查看运行结果。这种逆向需求通常不是很多,典型的工种有杀软厂商的病毒分析工程师。

功能逆向相比流程逆向则困难得多。但需求比较普遍。实际逆向分析过程中对功能实现的理解,在很大程度上取决于逆向人员相关的软件开发知识。比如,分析Android程序的JAVA代码就需要掌握基本的Android软件开发的知识。分析so库的代码就需要了解C/C++相关的so库开发的知识。除了基本开发相关的能力外,逆向分析人员还需要具备以下知识:

ARM/X86/MIPS汇编语言-分析so库时可能需要阅读大量的反汇编代码。

常见逆向分析工具的使用-JDGUI/IDA PRO/APKTOOL/JEB/DEX2JAR

常用的安卓程序调试与反调试手段-调试器检测与反检测/脱壳/反混淆

常用的加密与解密算法-好的逆向分析人员需要有快速识别常见加密解密算法的能力

最后,就是多动手,多动手练习是掌握逆向分析技术最好的方法。

未经允许不得转载:便宜VPS网 » windows驱动逆向(windows驱动教程)