内核驱动反编译笔记4
if else啦
需要掌握:
if else在程序反汇编中的状态,用16进制编辑器修改程序
cmp 比较
jbe 小于等于
jmp 无条件转移
shl 数值左移:左移一位(shl ecx,1)等于乘2,左移2位等于乘4
add 加
需要了解:
jg,jl,jgl 大于,小于,大于等于
PUSH 入栈同时esp-4
POP 出栈同时esp+4
用16进制编辑器修改程序
命令(16进制代码)
JA/JNBE (77)
JAE/JNB (73)
JB/JNAE (72)
JBE/JNA (76)
JG/JNLE (7F)
JGE/JNL (7D)
JL/JNGE (7C)
JLE/JNG (7E)
无需了解
call与ret对esp的影响
右移shr
正确的来说左移和右移操作是操作数乘于(或除于)2的平方((SHL)n * 2 ^ 2、(SHR)n / 2 ^ 2)。
即操作数每向左或右移动一次都乘于或除于2一次。
文件校验和
/////////////
ULONG MyAdd1(ULONG u1,ULONG u2)
{
ULONG u3;
if (u1>u2)
u3=u1*2;
else
u3=u2*4;
return u3+100;
}
使用:
MyAdd1(5,8)
////////////
kd> uf bz5!myadd1
bz5!MyAdd1 [d:\mydriver\bz5\bz5.c @ 7]:
7 f8513490 8bff mov edi,edi
7 f8513492 55 push ebp
7 f8513493 8bec mov ebp,esp
7 f8513495 51 push ecx
//这里开始
9 f8513496 8b4508 mov eax,dword ptr [ebp+8] ;5
9 f8513499 3b450c cmp eax,dword ptr [ebp+0Ch] ;将5与8比较
9 f851349c 760a jbe bz5!MyAdd1+0x18 (f85134a8) ;小于等于就跳转到f85134a8运行
bz5!MyAdd1+0xe [d:\mydriver\bz5\bz5.c @ 10]:
10 f851349e 8b4d08 mov ecx,dword ptr [ebp+8]
10 f85134a1 d1e1 shl ecx,1
10 f85134a3 894dfc mov dword ptr [ebp-4],ecx
11 f85134a6 eb09 jmp bz5!MyAdd1+0x21 (f85134b1)
bz5!MyAdd1+0x18 [d:\mydriver\bz5\bz5.c @ 12]:
12 f85134a8 8b550c mov edx,dword ptr [ebp+0Ch] ;8
12 f85134ab c1e202 shl edx,2 ;8*4
12 f85134ae 8955fc mov dword ptr [ebp-4],edx ;32
bz5!MyAdd1+0x21 [d:\mydriver\bz5\bz5.c @ 14]:
14 f85134b1 8b45fc mov eax,dword ptr [ebp-4] ;32
14 f85134b4 83c064 add eax,64h ;32+100 准备返回
//赋值给eax作为返回值结束
16 f85134b7 8be5 mov esp,ebp
16 f85134b9 5d pop ebp
16 f85134ba c20800 ret 8
最后运行结果:
kd> g
x3 Result:132
!
当我把
if (u1>u2)
改为
if (u1<u2)
反汇编以后:
9 f8567499 3b450c cmp eax,dword ptr [ebp+0Ch]
9 f856749c 730a jae bz5!MyAdd1+0x18 (f85674a8)
运行结果:
kd> g
x3 Result:110
!
内核反编译学习笔记4(下)附windbg常用命令
那么我们能否把原来的730a改为7f0a这样的手段,修改驱动的判断呢?
当然可以,我们可以用ultraedit等编辑器,打开bz5.sys,搜索"3b450c",下面的73改为自己需要的:
命令(16进制代码)
JA/JNBE (77)
JAE/JNB (73)
JB/JNAE (72)
JBE/JNA (76)
JG/JNLE (7F)
JGE/JNL (7D)
JL/JNGE (7C)
JLE/JNG (7E)
比如7F,保存,然后注册运行。没错,你会发现不能运行。
////////////////////////
解决方法:重新计算校验和并保存。
用loadPe就可以了,里面有校验和,旁边有个问号,重新计算以后别忘了保存,再确定,然后,阿弥陀佛。
1.基本调试控制
运行程序(Run): 快捷键:F5 命令:g
单步步入(Step In): 快捷键:F8 命令:p
单步步过(Step Over): 快捷键:F10
运行到光标所在行: 快捷键:F7
执行到返回:gu
执行到指定地址:g [Address]
重新运行调试程序: 快捷键:Ctrl+Shift+F5(这个对驱动一般用不到)
2.断点
断点之于调试当然是非常重要的
常用命令:
bp [Address]or[Symbol] 在指定地址下断
可以使用地址或符号,如
bp 80561259(Windbg默认使用16进制)
bp MyDriver!GetKernelPath
bp MyDriver!GetKernelPath+0x12
bp [Address] /p eprocess 仅当当前进程为eprocess时才中断
这个很常用,比如你bp nt!NtTerminateProcess,但是只想在某一进程触发此断点时才断下来,那就加上这个参数吧,因为内核中的代码是各个进程共用的,所以此命令很实用
bp [Address] /t ethread 仅当当前线程为ethread时才中断,用法跟/p参数类似
bu [Address]or[Symbol] 下一个未解析的断点(就是说这个断点需要延迟解析)
这个也很常用,比如我们的驱动名为MyDriver.sys,那么在驱动加载之前下断bu MyDriver!DriverEntry,
然后加载这个驱动时就可以断在驱动入口,并且这个是不需要调试符号支持的
bl 列出所有断点,L=List
bc[id] 清除断点,c=Clear,id是bl查看时的断点编号
bd[id] 禁用断点,d=Disable,id即断点编号
be[id] 启用断点,e=Enable,id为断点编号
3.查看和修改数据
调试中不可避免的要查看和修改数据
查看内存:
db/dw/dd/dq [Address] 字节/字/双字/四字方式查看数据
da/du [Address] ASCII字符串/Unicode字符串方式查看指定地址
其它常用的如查看结构
dt nt!_EPROCESS
dt nt!_EPROCESS 89330da0 (把0x89330da0作为对象指针)
修改内存:
eb/ew/ed/eq/ef/ep Address [Values]
字节/字/双字/四字/浮点数/指针/
ea/eu/eza/ezu Address [Values]
ASCII字符串/Unicode字符串/以NULL结尾的ASCII字符串/以NULL结尾的Unicode字符串
搜索内存:
s -[b/w/d/q/a/u] Range Target
搜索字节/字/双字/四字/ASCII字符串/Unicode字符串
4.寄存器
在用Windbg调试时可以Alt+4直接调出寄存器窗口,然后拖放到合适的位置就可以。
要修改呢就直接双击相应的项就可以了。
把命令的方式也说一下,比较简单:
r 显示所有寄存器的值
r eax 显示eax的值
r eax=1 修改eax的值为1
5.辅助命令
!process 显示当前进程信息
!process 0 0 显示当前所有进程(会有僵尸进程)
!process 1f4 显示pid为1f4的进程信息,后面也可以跟eprocess的值
!thread 显示当前线程信息
!thread
!process 1f4 显示tid为768的线程信息,后面也可以跟ethread的值
栈相关:
k 显示调用栈
kb 显示ebp和前3个参数
kp 以函数调用形式显示栈