阅读:1886回复:2
一款红外usb NDIS-IRDA-USB反汇编及重写
背景:
最近公司有个红外项目,买了个usb口的红外ir650,只有xp下的驱动文件,项目要求我将这个irda移植到winCE上,并且在xp上也要进行加解密操作。考虑了下决定反汇编先 重写xp下的驱动再移植到ce上,不再另外买串口的红外了(串口红外ddk有例子)。给反汇编核ndis-usb初学者看 开发工具:IDA、WinDBG、VMare、DDK、串口线(双机调试用) 返汇编代码分析: start函数就是DriverEntry INIT:00015A4C mov byte ptr [ebp+var_6C], 5 INIT:00015A50 mov byte ptr [ebp+var_6C+1], 0 INIT:00015A54 mov [ebp+var_64], 0 INIT:00015A5B mov [ebp+var_58], offset MiniportHalt ; complet INIT:00015A62 mov [ebp+var_50], offset MiniportInit ; complete INIT:00015A69 mov [ebp+var_48], offset MiniportQuery ; complete INIT:00015A70 mov [ebp+var_44], 0 INIT:00015A77 mov [ebp+var_40], offset MiniportReset ; complete INIT:00015A7E mov [ebp+var_3C], offset MiniportSend ; complete INIT:00015A85 mov [ebp+var_38], offset MiniportSetInfo ; complete INIT:00015A8C mov [ebp+var_34], 0 INIT:00015A93 mov [ebp+var_54], 0 INIT:00015A9A mov [ebp+var_4C], 0 INIT:00015AA1 mov [ebp+var_60], 0 INIT:00015AA8 mov [ebp+var_5C], 0 INIT:00015AAF mov [ebp+var_30], offset ReturnPacket ; complete INIT:00015AB6 mov [ebp+var_2C], 0 INIT:00015ABD mov [ebp+var_28], 0 函数名字需要自己改,上面这段是填充NDIS50_MINIPORT_CHARACTERISTICS INIT:00015B05 mov edx, [ebp+arg_0] INIT:00015B08 mov dword ptr [edx+38h], offset Create_Close ; completed INIT:00015B0F mov eax, [ebp+arg_0] INIT:00015B12 mov dword ptr [eax+40h], offset Create_Close ; completed INIT:00015B19 mov ecx, [ebp+arg_0] INIT:00015B1C mov dword ptr [ecx+70h], offset DeviceControl ; completed INIT:00015B23 mov eax, [ebp+var_4] 上面这段是 DriverObject->MajorFunction[IRP_MJ_CREATE] = Create_Close; // completed DriverObject->MajorFunction[IRP_MJ_CLOSE] = Create_Close; // completed DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceControl; 由于是ndis-wdm(usb)所以要处理irp。 DriverEntry需要的就是这些,实际上ir650用的usb-serial,所以只注册了这些函数,并且是SIR编码速率低。 重点在MiniportInit函数里,对应普通usb驱动AddDevice里的操作都在该函数里实现,包括匹配PID,配置usb endpoint,及初始化发送接受线程、DPC等。 .text:00010BBF mov edx, [ebp+arg_0] .text:00010BC2 add edx, 1F8h .text:00010BC8 mov eax, [ebp+arg_0] .text:00010BCB mov [eax+1FCh], edx .text:00010BD1 mov ecx, [ebp+arg_0] .text:00010BD4 mov edx, [ebp+arg_0] .text:00010BD7 mov eax, [edx+1FCh] .text:00010BDD mov [ecx+1F8h], eax 这种代码就是调用InitializeListHead反出来的代码 调用NdisMSetAttributesEx时注意参数,这个驱动里用了NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND .text:00010F59 mov eax, [ebp+ListEntry] .text:00010F5C push eax ; StartContext .text:00010F5D push offset StartRoutine ; StartRoutine .text:00010F62 push 0 ; ClientId .text:00010F64 push 0 ; ProcessHandle .text:00010F66 push 0 ; ObjectAttributes .text:00010F68 push 0 ; DesiredAccess .text:00010F6A mov ecx, [ebp+ListEntry] .text:00010F6D add ecx, 4Ch .text:00010F70 push ecx ; ThreadHandle .text:00010F71 call ds:PsCreateSystemThread 该线程函数主要处理一些irp操作,起调度作用。 .text:00010FA6 push 0 ; 2008-10-03 18:14 conding... .text:00010FA8 push 0 .text:00010FAA mov ecx, [ebp+ListEntry] .text:00010FAD add ecx, 0Ch .text:00010FB0 push ecx .text:00010FB1 push 0 .text:00010FB3 push 0 .text:00010FB5 mov edx, [ebp+ListEntry] .text:00010FB8 mov eax, [edx+18h] .text:00010FBB push eax .text:00010FBC call ds:NdisMGetDeviceProperty 这段函数很重要,获得NextDeviceObject。 .text:000143B5 mov ecx, [ebp+pUrb] .text:000143B8 mov word ptr [ecx+2], 0Bh ; _URB_HEADER.Function = URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE .text:000143BE mov edx, [ebp+pUrb] .text:000143C1 mov word ptr [edx], 50h ; _URB_HEADER.Length .text:000143C6 mov eax, [ebp+pUrb] .text:000143C9 mov dword ptr [eax+18h], 9 ; _URB_CONTROL_DESCRIPTOR_REQUEST.TransferBufferLength .text:000143D0 mov ecx, [ebp+pUrb] .text:000143D3 mov dword ptr [ecx+20h], 0 ; _URB_CONTROL_DESCRIPTOR_REQUEST.TransferBufferMDL .text:000143DA mov edx, [ebp+pUrb] .text:000143DD mov eax, [ebp+PUSB_CONFIGURATION_DESCRIPTOR] .text:000143E0 mov [edx+1Ch], eax ; _URB_CONTROL_DESCRIPTOR_REQUEST.TransferBuffer = PUSB_CONFIGURATION_DESCRIPTOR .text:000143E3 mov ecx, [ebp+pUrb] .text:000143E6 mov byte ptr [ecx+4Bh], 2 ; _URB_CONTROL_DESCRIPTOR_REQUEST.DescriptorType = USB_CONFIGURATION_DESCRIPTOR_TYPE .text:000143EA mov edx, [ebp+pUrb] .text:000143ED mov byte ptr [edx+4Ah], 0 ; _URB_CONTROL_DESCRIPTOR_REQUEST.Index = 0 这种代码一般就是填从URB结构,有一系列函数的,这个是调用UsbBuildGetDescriptorRequest。 对于usb-control端点的写没必要设置完成例程,反出来的结果。还有些usbd的函数 USBD_CreateConfigurationRequest、USBD_ParseConfigurationDescriptorEx 在配置接收函数时需要设置irp完成例程函数,在完成里程里再重新配置接收函数,这段返回编代码我就不贴了,太长。 .text:0001279C off_1279C dd offset loc_1251E ; DATA XREF: IrToNdis_124A0+77r .text:000127A0 dd offset loc_1253E .text:000127A4 dd offset loc_12736 .text:000127A8 dd offset loc_1268C .text:000127AC dd offset loc_125B9 .text:000127B0 off_127B0 dd offset loc_126F7 ; DATA XREF: IrToNdis_124A0+218r .text:000127B4 dd offset loc_126DB .text:000127B8 dd offset loc_126BF .text:000127BC dd offset loc_12734 .text:000127C0 byte_127C0 db 0 ; DATA XREF: IrToNdis_124A0+212r .text:000127C1 dd 7 dup(3030303h), 1030303h, 10h dup(3030303h), 1020303h .text:000127C1 dd 7 dup(3030303h), 303h, 2 dup(0CCCCCCCCh) .text:0001284D align 10h 这种代码不用想,几乎就是switch()case反出来的代码,不要被吓着,仔细分析,在结合你分析的汇编代码, 比如红外码转化,可以比较轻松将这段代码重新写出来 还有就是由于是ndis-usb,没有irp,irp需要你上面的NextDeviceObject创造出来 在MiniportQuery和set函数中,需要对OID_IRDA_SUPPORTED_SPEEDS和OID_IRDA_MEDIA_BUSY,如果oid错误, 很有可能导致你上层应用程序socket或getsocketopt不成功。 在MiniportSend中,返回STATUS_PENDING,在你的IRP完成例程里调用NdisMSendComplete指示发包完成 代码编写完调试: 用虚拟机和双机调试,具体怎么配置,google搜下很多教程。 根据反汇编代码写的驱动基本会出现错误,建议在编写的时候一定要仔细,不然调试的时候会很烦。 在你的驱动不死机的时候你会发现socket或getsocketopt不成功,检查你的Oid和汇编代码是否一致。 socket成功后继续发现你的驱动让你ir650设备不闪灯不发红外包,请重新重头到尾检查你的代码, 没有办法,也许一个微小的错误会让你的设备不工作。 虚拟机调试usb的问题: 我的驱动能发包后发现在接收红外包的时候速度异常慢虽然可以接收文件,而且丢包率其高,感觉不是代码不正确, 换上正牌驱动居然出现和我的驱动一样的问题,并且还有时死机,我的驱动和正牌驱动死机的dump bug一寞一样, 偶然不用虚拟机调试,直接上机器,问题解决了,看来vmare的usb模拟的不是很好,赫赫,我用的是5.0。 现在调试兰芽usb我都用双机调试,虚拟机到有点不敢用了,不知道6.0还有没有这个bug 总结: 反汇编觉得最重要的是你要把驱动的全局变量要莫清楚,里面的数据结构代表了整个程序的架构和流程,很重要, 不明白的地方先标上,以后明白了再补,表出来了,难度基本就没了。 前后将近一个月时间连反带重写,中间还生病一个星期,驱动文件手上机器没有下次传上来吧,欢迎讨论 过几天奉上将ndis-irda-usb winxp驱动移植到winCE上。 |
|
沙发#
发布于:2008-10-26 09:28
不错:)
|
|
|
板凳#
发布于:2008-12-04 20:05
ce驱动移植完毕一直有事情现在才发上来,由于没有用ce的ndis-irda架构,估将MiniportInit中的代码放到adddevice(好像是这个名字,有点忘了)中,windows驱动中的dpc历程可以去掉,将这段代码放到issue那个函数注册中断endpoint即可,其他就没有什么了
|
|