pc蛋蛋赚钱有什么与众不同?

x86如何用汇编把PC主板上的扬声器弄响
&&&&& x86架构的计算机主板上均有一块8253定时计数器,其中定时器0产生心跳频率,定时器1忘记干吗用的了,定时器2输出的脉冲用来控制主板上一块简陋的蜂鸣器发出简陋的声音。但是在没有声卡没有扬声器的年代,这片简陋的蜂鸣器就是PC机唯一的发声器件。&&&&& 根据http://www.yibiaont.cn/iphoneiphone3688.html的文章,我得到了如下的一幅图。&&&&&&&&& 到这里基本上就了然了,想要蜂鸣器接受到与门输出的脉冲,需要满足两个条件:&&&&&&&& 1.0x61地址的bit1高电平&&&&&&&& 2.定时器2可工作&&&&&&&& 3.定时器2输出特定频率的方波信号在这个思想的指导下,我们可以很方便地让这片蜂鸣器发出简陋的声音。通过改变定时器2的输出频率,即可改变蜂鸣器发出的声音的频率。并且定时器2一旦被激活,则自动工作,不再需要CPU干预。这也意味着你的蜂鸣器会一直响,理论上讲你需要再写程序停止定时器2的工作,或者OS调用某个需要使用蜂鸣器的功能,才能停掉。下面这段汇编程序可以在任何x86架构的PC上运行,从8086到现在的酷睿处理器都可以。代码如下:CODE&&&&&&& SEGMENT&&&&&&&& ASSUME&&& CS:CODE,DS:DATA,SS:STKSTART:&&&&&&&& IN&&&& AL,61H&&&&&&&& OR&&& AL,B;将0x61地址的bit0和bit1置1&&&&&&&& OUT 61H,AL&&&&&&&&& MOV&&&&&&&& AL,B;定时器2状态3&&&&&&&& OUT 43H,AL&&&&&&&&& MOV&&&&&&&& AL,000H&&&&&&&& OUT 42H,AL;写高字节&&&&&&&&& MOV&&&&&&&& AL,0FH&&&&&&&& OUT 42H,AL;写低字节,然后就响了&&&&&&&&& MOV&&&&&&&& AH,4CH&&&&&&&& INT&& 21H;退出程序,返回DOS&CODE&&&&&&& ENDS&&&&&&&& END START&版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0外网网址:http://hi.baidu.com/albertdiao/blog/item/71b16562c7def3cd8cb10d68.html
分享这篇日志的人也喜欢
小年新年新气象
早上好我在等你?
第一次半夜播
起床啦宝宝们
听说早起的鸟儿有虫吃?
播到死想破70W
热门日志推荐
人人最热标签
北京千橡网景科技发展有限公司:
文网文[号··京公网安备号·甲测资字
文化部监督电子邮箱:wlwh@vip.sina.com··
文明办网文明上网举报电话: 举报邮箱:&&&&&&&&&&&&
请输入手机号,完成注册
请输入验证码
密码必须由6-20个字符组成
下载人人客户端
品评校花校草,体验校园广场黑大帅鸡蛋 吉林省唯一一家黄粉虫鸡蛋
用微信扫描二维码分享至好友和朋友圈
  “黑大帅”鸡&#x86产&#x81长白山脚下,牡丹江畔的敦化市大荒地村南山&#x679
原标题:黑大帅鸡蛋 吉林省唯一一家黄粉虫鸡蛋
  “黑大帅”鸡&#x86产&#x81长白山脚下,牡丹江畔的敦化市大荒地村南山林区,生态&#x73境&#x7净,整个鸡&#x86生产过程严格按照&#x7色&#x98品生产标准实&#x65质&#x91控制,&#x86鸡主要以黄粉虫为主&#x98,配以多&#x79中草药,玉米粉、熟豆粉为辅。打开一枚黑大帅鸡&#x86,你会看到它&#x86清稠厚、&#x9度大,&#x86清发黄,&#x86黄圆凸呈橙色,取&#x51后,&#x4&#x80&#x4持高挺形态,黑大帅鸡&#x86天然味道香醇、无腥味,口感有劲道。  “黑大帅”鸡&#x86也&#x53称作是黄粉虫鸡&#x86。黄粉虫俗称面包虫,&#x5含高&#x86白质、&#x77物质等17&#x79氨&#x57酸。黄粉虫其&#x72特的多&#x79营养有易于消化和吸收,随着社会发展,&#x4&#x4逐渐认识到黄粉虫是&#x7色&#x98品,把它誉为“&#x86白质&#x98品宝库”。  咨询电&#x8:0433-6570555  本报记者 田贝尼 G
用微信扫描二维码分享至好友和朋友圈
04/21 07:02
04/21 07:02
04/21 07:02
04/21 06:49
04/21 11:28
04/13 09:27
04/13 09:27
04/13 09:27
04/13 09:27
04/13 09:28
12/03 09:23
12/03 09:07
12/03 08:12
12/03 08:12
12/03 09:26
09/07 09:38
09/07 09:38
09/07 09:39
09/07 09:39
09/07 09:39
04/26 09:49
04/23 08:47
04/23 08:57
04/23 09:14
04/23 09:22
凤凰新闻官方微信
播放数:194353
播放数:124395
播放数:173975
播放数:82180
48小时点击排行[原创]windows7内核分析之x86&x64第二章系统调用
2.1内核与系统调用上节讲到进入内核五种方式 其中一种就是 系统调用 syscall/sysenter或者int 2e(在 64 位环境里统一使用 syscall/sysret 指令,在 32 位环境里统一使用 sysenter/sysexit 在 compatibility 模式下必须切换到 64 位模式,然后使用 syscall/sysret 指令&注释:32位cpu是x86模式 也叫legacy模式 再说清楚点 就是包含了实模式:可以执行以前的16位程序 也包含了保护模式:可以执行32位的程序 64位cpu是long模式:分为两种 64位模式:只执行64位的程序和compatibility模式:可以执行x86模式的程序&老式的cpu不支持 不提供sysenter指令,只能由int&2e模拟中断方式进入内核,调用系统服务)这两者什么区别呢?1,Int 2e速度慢 首先从TSS中加载内核堆栈的ss esp-&保存5个寄存器的现场(ss esp eip eflags cs)-&然后还要去IDT中查找isr,这个过程消耗的时间太多2,sysenter 提供了三个MSR寄存器 分别是SYSENTER_CS_MSR SYSENTER_EIP_MSR SYSENTER_ESP_MSR 分别指示了内核对应处理例程的cs选择子(函数所在段的选择子 通过选择子找到GDT 从逻辑地址转换为线性地址 最后访问线性地址 会根据四级表转换为物理地址)和内核函数地址和内核堆栈地址 这样就省去了查找idt表 TSS段 获得内核函数地址和内核堆栈地址 节省了大量时间++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++以下是X64的syscall 讲解 参考总结++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++syscall 的内核入口点是 KiSystemCall64() ,系统在 KiInitializeBootStructures() 里对 syscall/sysret 执行环境进行了设置:nt!KiInitializeBootStructures+0x233:
fffff800`03f12f63&498b442408&&&&&&mov&&&&&rax,qword&ptr&[r12+8]
fffff800`03f12f68&b&&&&&&mov&&&&&ecx,68h
fffff800`03f12f6d&&&&&&&&&mov&&&&&word&ptr&[rax+66h],cx
fffff800`03f12f71&48b02300&mov&rax,00h
fffff800`03f12f7b&b&&&&&&mov&&&&&ecx,0C0000081h&&&&&&&&&&&&&&&&&&&&&&&&&;&MSR_STAR
fffff800`03f12f80&488bd0&&&&&&&&&&mov&&&&&rdx,rax
fffff800`03f12f83&48c1ea20&&&&&&&&shr&&&&&rdx,20h
fffff800`03f12f87&0f30&&&&&&&&&&&&wrmsr
fffff800`03f12f89&488d05701cdbff&&lea&&&&&rax,[nt!KiSystemCall32&(fffff800`03cc4c00)]
fffff800`03f12f90&b&&&&&&mov&&&&&ecx,0C0000083h&&&&&&&&&&&&&&&&&&&&&&&&&;&MSR_CSTAR
fffff800`03f12f95&488bd0&&&&&&&&&&mov&&&&&rdx,rax
fffff800`03f12f98&48c1ea20&&&&&&&&shr&&&&&rdx,20h
fffff800`03f12f9c&0f30&&&&&&&&&&&&wrmsr
fffff800`03f12f9e&488d051b1fdbff&&lea&&&&&rax,[nt!KiSystemCall64&(fffff800`03cc4ec0)]
fffff800`03f12fa5&b&&&&&&mov&&&&&ecx,0C0000082h&&&&&&&&&&&&&&&&&&&&&&&&&;&MSR_LSTAR
fffff800`03f12faa&488bd0&&&&&&&&&&mov&&&&&rdx,rax
fffff800`03f12fad&48c1ea20&&&&&&&&shr&&&&&rdx,20h
fffff800`03f12fb1&0f30&&&&&&&&&&&&wrmsr
fffff800`03f12fb3&b&&&&&&mov&&&&&eax,4700h
fffff800`03f12fb8&b&&&&&&mov&&&&&ecx,0C0000084h&&&&&&&&&&&&&&&&&&&&&&&&&;&MSR_SFMASK
fffff800`03f12fbd&488bd0&&&&&&&&&&mov&&&&&rdx,rax
fffff800`03f12fc0&48c1ea20&&&&&&&&shr&&&&&rdx,20h
fffff800`03f12fc4&0f30&&&&&&&&&&&&wrmsr
fffff800`03f12fc6&85ed&&&&&&&&&&&&test&&&&ebp,ebp
fffff800`03f12fc8&750a&&&&&&&&&&&&jne&&&&&nt!KiInitializeBootStructures+0x2a4&(fffff800`03f12fd4)MSR_STAR 寄存器里的值被设为 00h,它意味着:SYSCALL_EIP 为 0SYSCALL_CS 为 0x10SYSRET_CS 为 0x23在 SYSRET_CS 中,SYSRET_CS.RPL = 3 返回的权限级别是 3 级(用户代码)。&MSR_CSTAR 寄存器被设为 nt!KiSystemCall32 (fffff800`03cc4c00) 地址值,这是为了 compaitibility 模式代码调用而设置的。MSR_LSTAR 寄存器被设为 nt!KiSystemCall64 (fffff800`03cc4ec0) 地址值,是为 64-bit 模式而准备的。CSTAR 寄存器为 compatibility 模式下的代码提供 rip 值,当 processor 在 comatibility 模式下运行时,执行了 syscall 指令,此时 rip 值将从 MSR_STAR 寄存器中加载。请记住:只能在 AMD 的 processor 使用 compaitibility 模式下的调用。照顾通用性,为了在 Intel 和 AMD 的 processor 上都能够使用 fast call 功能,操作系统的设计者应该要避免在 comaptibility 模式下使用 syscall 指令。前面提到过,建议在 compatibility 模式下先切换到 64-bit 模式后,再执行 syscall 指令;&NtReadFile
.text:7DE8F905&&&&&&&&&&&&&&&&&mov&&&&&ecx,&1Ah
.text:7DE8F90A&&&&&&&&&&&&&&&&&lea&&&&&edx,&[esp+FileHandle]
.text:7DE8F90E&&&&&&&&&&&&&&&&&call&&&&large&dword&ptr&fs:0C0h&//注意在win7x64&long模式下的&运行32位程序&就会进入兼容模式下&兼容模式下调用NtReadFile&这里就是上面说的必须切换到64位模式&这个函数里面&就是切换模式的&完后调用syscall
.text:7DE8F915&&&&&&&&&&&&&&&&&add&&&&&esp,&4
.text:7DE8F918&&&&&&&&&&&&&&&&&retn&&&&24hMSR_SFMASK 寄存器设为 4700h,意味着:NT DF IF TF这些 rflags 寄存器中的标志位在进入 KiSystemCall64() 后会被清 0在 long mode(win7 x64 ) 下,当执行 syscall 指令时,当前的 rflags 寄存器值被保存在 r11 寄存器,processor 在执行 syscall 时,准备的目标执行环境中,rflags 将会根据 SFMASK 寄存器的值进行设置:如果 SFMASK 寄存器的某一位置为 1,那么 rflags 寄存器中相应的位将会被清 0,置为 0 时,rflags 寄存器中相应位不变它的逻辑 C 描述为:rflags = rflags & (~sfmask);你应该在系统服务例程先保存 r11 值(原来的 rflags 寄存器值),以便 sysret 执行返回时可以恢复原来的 rflags 值&那么,对于要进入系统调用的代码来说:ntdll!NtReadFile:
ad410&4c8bd1&&&&&&&&&&&mov&&&&&r10,rcx&//保存原来的rcx
ad413&b&&&&&&&mov&&&&&eax,3&//系统调用号&这里NtReadFile的内核号码是3
ad418&0f05&&&&&&&&&&&&&&Syscall
ad41a&c3&&&&&&&&&&&&&&&&ret执行 syscall 后,rcx 会保存返回值,因此应该要保存 rcx 原来的值。&KiSystemCall64&&proc&near
&&&& swapgs//将gs的基址与MSR[c0000102]内容互换,设置过后gs:0指向内核处理器控制域_KPCR
&&&&& mov&&&&&gs:10h,&rsp//将用户态堆栈指针保存到_KPCR+0x010的成员UserRsp里
&&&&& mov&&&&&rsp,&gs:1A8h//使用_KPCR+0x1A8的成员RspBase设置当前rsp,这个成员存储了当前线程核心态的堆栈指针
&&&&&&&&&&push&&&&2Bh
&&&&&&&&&&push&&&&qword&ptr&gs:10h
&&&&&&&&&&push&&&&r11//r11里保存的是rflags
&&&&&&&&&&push&&&&33h
&&&&&&&&&&push&&&&rcx//&rcx里保存的是用户态syscall的下一条指令地址
&&&&&&&&&&mov&&&&&rcx,&r10//&把系统调用的第一个参数重新赋给rcx
&&&&&&&&&&sub&&&&&rsp,8
&&&&&&&&&&push&&&&rbp
&&&&&&&&&&sub&&&&&rsp,158h//&rsp与设置伊始相比共减少了0x190字节。期间恢复了rcx,在堆栈上保存了一些值。使用下面的命令,我们可以看出,0x190正是_KTRAP_FRAME的大小:
&&&&&&&&&&lea&&&&&rbp,&[rsp+190h+var_110]//现在rsp指向_KTRAP_FRAME的起始地址,rbp指向_KTRAP_FRAME+0x80的位置
(4)&&&&& mov&&&&&[rbp+0C0h],rbx
&&&&&&&&&&mov&&&&&[rbp+0C8h],&rdi
&&&&&&&&&&mov&&&&&[rbp+0D0h],&rsi
&&&&&&&&&&mov&&&&&byte&ptr&[rbp-55h],&2
(5)&&&&& mov&&&&&rbx,&gs:188h
&&&&&&&&&&prefetchw&byte&ptr&[rbx+1D8h]
&&&&&&&&&&stmxcsr&dword&ptr&[rbp-54h]
&&&&&&&&&&ldmxcsr&dword&ptr&gs:180h
(6)&&&&& cmp&&&&&byte&ptr&[rbx+3],0//是否在被调试&调试就保存寄存器
(7)&&&&&&&&&&&mov&&&&&word&ptr&[rbp+80h],0
&&&&&&&&&&jz&&&&&&loc_
&&&&&&&&&&mov&&&&&[rbp-50h],&rax
(7)&&&&& mov&&&&&[rbp-48h],&rcx//以下若干条指令将rcx、rdx、r8、r9存入了_KTRAP_FRAME当中,其中rbp-48h相当于rsp+80g-48h即rsp+38h
&&&&&&&&&&mov&&&&&[rbp-40h],&rdx
&&&&&&&&&&test&&&&byte&ptr&[rbx+3],3
&&&&&&&&&&mov&&&&&[rbp-38h],&r8
&&&&&&&&&&mov&&&&&[rbp-30h],&r9++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++&+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++以下是X86的sysenter 讲解 参考总结++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++&ntdll!ZwReadFile:
776262dc&b&&&&&&mov&&&&&eax,111h//系统调用号
&ba0003fe7f&&&&&&mov&&&&&edx,offset&SharedUserData!SystemCallStub&(7ffe0300)//这个7ffe03000地址固定的&系统初始化&查看是否支持快速系统调用&支持&这个地址里面存的就是KiFastSystemCall&否则就是KiInitSystemCall(int&0x2e模拟中断)的地址&这些函数都存在于用户空间ntdll.dll(和内核ntdll不一样)中&这个dll&对于每个进程&地址不变&一直在内存中
7ffe03000&和0x7fe0000&一个是r3的地址&一个是内核的地址&两个64kb地址映射到同一个物理内存
&ff12&&&&&&&&&&&&call&&&&dword&ptr&[edx]
&c22400&&&&&&&&&&ret&&&&&24h
776262eb&90&&&&&&&&&&&&&&nop
ntdll!KiFastSystemCall:
&8bd4&&&&&&&&&&&&mov&&&&&edx,esp//进入KiFastSystemCall之前&已经被调用方压入了各种参数&最后压入的是返回地址&当前esp指向它&在书中&被压入堆栈的参数区域叫参数块&&处理完后&调用sysexit&出栈ret&返回
&0f34&&&&&&&&&&&&sysenter
Sysenter进入内核后&的总入口是KiFastCallEntry
和int2e的区别:快速系统调用的sysenter&堆栈地址保存在edx&返回地址保存在SharedUserData-&SystemCallReturn指向KiFastSystemCallRet地址
nt!KiFastCallEntry:
83e888e0&b&&&&&&mov&&&&&ecx,23h
83e888e5&6a30&&&&&&&&&&&&push&&&&30h
83e888e7&0fa1&&&&&&&&&&&&pop&&&&&fs//fs指向kpcr
83e888e9&8ed9&&&&&&&&&&&&mov&&&&&ds,cx//指向用户空间数据段
83e888eb&8ec1&&&&&&&&&&&&mov&&&&&es,cx
83e888ed&648b0d&&mov&&&&&ecx,dword&ptr&fs:[40h]//从kpcr获取TSS段的起点
83e888f4&8b6104&&&&&&&&&&mov&&&&&esp,dword&ptr&[ecx+4]//从TSS获取系统空间段的指针
83e888f7&6a23&&&&&&&&&&&&push&&&&23h//压栈r3的数据段选择子(模仿中断自陷&异常进入内核的指令&会自动堆栈上创建一个框架&这个框架结构一样&所以这里虽然是快速系统调用&但是也是进入内核&模仿自陷&中断&异常进入内核的函数入口样子&照猫画虎&但是注意int2e的内核入口函数没有照猫画虎&因为int&2e本身就是中断&所以cpu进入内核后&堆栈上已经画出老虎了
83e888f9&52&&&&&&&&&&&&&&push&&&&edx//压栈r3的esp
83e888fa&9c&&&&&&&&&&&&&&pushfd//压栈r3的eflags
83e888fb&6a02&&&&&&&&&&&&push&&&&2
83e888fd&83c208&&&&&&&&&&add&&&&&edx,8//跳过用户堆栈的参数块
83e88900&9d&&&&&&&&&&&&&&popfd//r0的eflags&所有标志都为0&中断关闭
83e0102&&&&&&or&&&&&&byte&ptr&[esp+1],2
83eb&&&&&&&&&&&&push&&&&1Bh//模仿自陷中断异常的push&cs&eip83e88908&ff350403dfff&&&&push&&&&dword&ptr&ds:[0FFDF0304h]//KiFastSystemCallRet地址
83e&&&&&&&&&&&&push&&&&0//这里以下见①注释
83e88910&55&&&&&&&&&&&&&&push&&&&ebp
83e88911&53&&&&&&&&&&&&&&push&&&&ebx
83e88912&56&&&&&&&&&&&&&&push&&&&esi
83e88913&57&&&&&&&&&&&&&&push&&&&edi
83ed1c000000&&mov&&&&&ebx,dword&ptr&fs:[1Ch]
83eb&&&&&&&&&&&&push&&&&3Bh
83e4010000&&&&mov&&&&&esi,dword&ptr&[ebx+124h]
83e88923&ff33&&&&&&&&&&&&push&&&&dword&ptr&[ebx]
83e8ffffffff&&&&mov&&&&&dword&ptr&[ebx],0FFFFFFFFh
83ee28&&&&&&&&&&mov&&&&&ebp,dword&ptr&[esi+28h]
83e&&&&&&&&&&&&push&&&&1
83e&&&&&&&&&&sub&&&&&esp,48h
83ec020000&&&&sub&&&&&ebp,29Ch
83e8a&&mov&&&&&byte&ptr&[esi+13Ah],1
83e88940&3bec&&&&&&&&&&&&cmp&&&&&ebp,esp
83e&&&&&&&&&&&&jne&&&&&nt!KiFastCallEntry2+0x49&(83e888db)
83ec00&&&&&&&&and&&&&&dword&ptr&[ebp+2Ch],0
83e8df&&&&&&&&test&&&&byte&ptr&[esi+3],0DFh
83e010000&&&&mov&&&&&dword&ptr&[esi+128h],ebp
83e8feffff&&&&jne&&&&&nt!Dr_FastCallDrSave&(83e88790)
83ed60&&&&&&&&&&mov&&&&&ebx,dword&ptr&[ebp+60h]
83ed68&&&&&&&&&&mov&&&&&edi,dword&ptr&[ebp+68h]
83ec&&&&&&&&&&mov&&&&&dword&ptr&[ebp+0Ch],edx
83e800ddbba&&mov&&&&&dword&ptr&[ebp+8],0BADB0D00h
83e&&&&&&&&&&mov&&&&&dword&ptr&[ebp],ebx
83e&&&&&&&&&&mov&&&&&dword&ptr&[ebp+4],edi
83e8896e&fb&&&&&&&&&&&&&&sti
83e&&&&&&&&&&&&mov&&&&&edi,eax
83e8&&&&&&&&&&shr&&&&&edi,8
83e&&&&&&&&&&and&&&&&edi,10h
83e88977&8bcf&&&&&&&&&&&&mov&&&&&ecx,edi
83e88979&03bebc000000&&&&add&&&&&edi,dword&ptr&[esi+0BCh]
83e&&&&&&&&&&&&mov&&&&&ebx,eax
83ef0000&&&&&&and&&&&&eax,0FFFh
83e8&&&&&&&&&&cmp&&&&&eax,dword&ptr&[edi+8]
83e3fdffff&&&&jae&&&&&nt!KiBBTUnexpectedRange&(83e886c2)
83e&&&&&&&&&&cmp&&&&&ecx,10h
83ea&&&&&&&&&&&&jne&&&&&nt!KiSystemServiceAccessTeb+0x12&(83e889ae)
83ee&&&&mov&&&&&ecx,dword&ptr&[esi+88h]
83e&&&&&&&&&&&&xor&&&&&esi,esi&+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++&&++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++以下是int 2e 讲解 &参考总结+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ntdll!ZwReadFile:
&&&&push&ebp
mov&ebp,esp
Mov&eax,111h//系统调用号
Lea&edx,[8+ebp]//指向参数块
Int&2e//不支持syscall/sysenter的cpu&只能用这个了
&&&&ret&&&&&9h&&&2.2系统调用的内核入口KiSystemService()上面讲到老的cpu是通过int 2e 模拟进入内核 而不是新cpu 直接支持快速系统调用那么KiSystemService()就是int 2e的处理函数 进入这个函数之前 cpu会自动读取TR寄存器 找到TSS段 读取里面的ss esp 就是内核堆栈地址了 完后往这个地址保存用户空间的堆栈 eflags cs eip 具体开头已经说了 这里就不废话了nt!KiSystemService:83e &&&&&&&&&&&push &&&0 &&//①是一种类似TrapFrame 进入这个函数之前 cpu会自动压入各种ss esp eip等等 你可以理解为一种上下文 这里push 0 是因为函数最后要把他的值存入eax当做状态码返回 另外就是操作系统 把这个Frame 定义了一个结构 然而异常发生后 cpu会自动压入一个错误码 中断和自陷都没有 所以为了通用 这个结构里面不管是异常还是中断进入内核 结构第一个元素都是0 占个位置的意思 83e88810 55 &&&&&&&&&&&&&push &&&ebp//保存栈帧83e88811 53 &&&&&&&&&&&&&push &&&ebx//函数下面要用到ebx 所以这里先保存一下83e88812 56 &&&&&&&&&&&&&push &&&esi//函数下面 要用到esi保存kthread 所以这先保存83e88813 57 &&&&&&&&&&&&&push &&&edi//函数下面 要用edi引用调用号 所以这也要保存83e &&&&&&&&&&&push &&&fs//内核fs指向kpcr 用户层指向TEB 所以这里提前保存 因为进了内核 fs要改变了83e88816 bb &&&&&mov &&&&ebx,30h//r0的fs指向kpcr fs和cs一样都是段选择子 所以这六30h是GDT的kpcr的索引表②:83eee3&&&&&&&&&&mov&&&&&fs,bx
83e8881e&bb&&&&&&mov&&&&&ebx,23h//数据段的选择子&见上图&内核中都规定好
83e88823&8edb&&&&&&&&&&&&mov&&&&&ds,bx
83e&&&&&&&&&&&&mov&&&&&es,bx
83e&&mov&&&&&esi,dword&ptr&fs:[124h]//使esi指向当前的ethread结构
83e&&push&&&&dword&ptr&fs:[0]//保存老的exceptionList
83effffffff&mov&dword&ptr&fs:[0],0FFFFFFFFh新的exceptionlist为空白
83e88840&ffb63a010000&&&&push&&&&dword&ptr&[esi+13Ah]//保存老的先前模式
83e&&&&&&&&&&sub&&&&&esp,48h//为之后要保存的调试寄存器&留下空间
83ec246c&&&&&&&&mov&&&&&ebx,dword&ptr&[esp+6Ch]//系统调用前夕的cs印象
83e&&&&&&&&&&and&&&&&ebx,1//0环最低位为0&&3环最低位为1
83ea010000&&&&mov&&&&&byte&ptr&[esi+13Ah],bl//新的先前模式
83e88856&8bec&&&&&&&&&&&&mov&&&&&ebp,esp
83ee&&&&mov&&&&&ebx,dword&ptr&[esi+128h]//kthread&结构里的TrapFrame&因为KiSystemService里面可能调用其他api&也会再次进入KiSystemService&梯归调用&那么肯定要梯归返回&所以需要提前保存好上下文&但是驱动可以搜索特征码&直接定位函数地址&绕过KiSystemService
83ec&&&&&&&&&&mov&&&&&dword&ptr&[ebp+3Ch],ebx//暂时保存在这里
83ec00&&&&&&&&and&&&&&dword&ptr&[ebp+2Ch],0//dr7&设置为0
83e8df&&&&&&&&test&&&&byte&ptr&[esi+3],0DFh//判断当前是否被调试
83e010000&&&&mov&&&&&dword&ptr&[esi+128h],ebp//新的TrapFrame是此时堆栈上的框架Frame
83e8886f&fc&&&&&&&&&&&&&&cld&//屏蔽中断
83eafeffff&&&&jne&&&&&nt!Dr_kss_a&(83e88710)//如果被调试&那么要保存好调试寄存器
83ed60&&&&&&&&&&mov&&&&&ebx,dword&ptr&[ebp+60h]//这里书上也没讲清楚&知道的告诉我一下
83ed68&&&&&&&&&&mov&&&&&edi,dword&ptr&[ebp+68h]
83ec&&&&&&&&&&mov&&&&&dword&ptr&[ebp+0Ch],edx
83e8887f&cddbba&&mov&&&&&dword&ptr&[ebp+8],0BADB0D00h
83e&&&&&&&&&&mov&&&&&dword&ptr&[ebp],ebx
83e&&&&&&&&&&mov&&&&&dword&ptr&[ebp+4],edi
83e8888c&fb&&&&&&&&&&&&&&sti//开启中断
83e8888d&e9dd000000&&&&&&jmp&&&&&nt!KiFastCallEntry+0x8f&(83e8896f)
nt!KiFastCallEntry+0x8f:
83e&&&&&&&&&&&&mov&&&&&edi,eax//系统调用号
83e8&&&&&&&&&&shr&&&&&edi,8//除以256
83e&&&&&&&&&&and&&&&&edi,10h//调用号是否大于1000
83e88977&8bcf&&&&&&&&&&&&mov&&&&&ecx,edi//00&或者10&nt4.0之前小于1000&那么ecx就是00&否则10
83e88979&03bebc000000&&&&add&&&&&edi,dword&ptr&[esi+0BCh]//kthread&结构里有一个ServiceTable指针&其实默认他不是指向KeServiceDescriptorTableShadow(win32k.sys)&就是指向KeServiceDescriptorTable(基本系统调用)也就是说每个线程&可以指向不同的表&脑洞大开&即使tp对KeServiceDescriptorTable做了手脚&你也可以提前备份一个表&完后让线程的ServiceTable指向它&KeServiceDescriptorTable[0]是1000以下的系统调用&[1]是1000以上的系统调用(KeServiceDescriptorTableShadow[1])&&里面每一项&都是一个结构&KService_Table_Descriptor&第一个元素就是MainSSDT,MainSSDT={{NtOpenFile},{NtCloseFile},{}......}
83e&&&&&&&&&&&&mov&&&&&ebx,eax
83ef0000&&&&&&and&&&&&eax,0FFFh//获取调用号的低12位
83e8&&&&&&&&cmp&&&&&eax,dword&ptr&[edi+8]//和上面KService_Table_Descriptor结构的Limit比较
83e3fdffff&&&&jae&&&&&nt!KiBBTUnexpectedRange&(83e886c2)//如果超了&肯定是大于1000那么就是shadow表里的&就跳到错误处理的地方&完后会加载win32k.sys&使当前线程指向KeServiceDescriptorTableShadow[1]
83e&&&&&&&&&&cmp&&&&&ecx,10h//如果是10&那么就是win32k调用
83ea&&&&&&&&&&&&jne&&&&&nt!KiSystemServiceAccessTeb+0x12&(83e889ae)
83ee&&&&mov&&&&&ecx,dword&ptr&[esi+88h]//使用win32k系统调用表&获取表项里面的地址&完后跳过去执行
83e&&&&&&&&&&&&xor&&&&&esi,esi
83e889ae&64ff05b0060000&&inc&&&&&dword&ptr&fs:[6B0h]
83e889b5&8bf2&&&&&&&&&&&&mov&&&&&esi,edx//使esi指向&用户空间堆栈上的参数块
83e889b7&33c9&&&&&&&&&&&&xor&&&&&ecx,ecx
83e889b9&8b570c&&&&&&&&&&mov&&&&&edx,dword&ptr&[edi+0Ch]
83e889bc&8b3f&&&&&&&&&&&&mov&&&&&edi,dword&ptr&[edi]//使edi指向具体的系统调用表
83e889be&8a0c10&&&&&&&&&&mov&&&&&cl,byte&ptr&[eax+edx]//函数指针
83e889c1&8b1487&&&&&&&&&&mov&&&&&edx,dword&ptr&[edi+eax*4]
83e889c4&2be1&&&&&&&&&&&&sub&&&&&esp,ecx//在系统空间上留出空间
83e889c6&c1e902&&&&&&&&&&shr&&&&&ecx,2
83e889c9&8bfc&&&&&&&&&&&&mov&&&&&edi,esp
83e889cb&f6457202&&&&&&&&test&&&&byte&ptr&[ebp+72h],2
83e889cf&7506&&&&&&&&&&&&jne&&&&&nt!KiSystemServiceAccessTeb+0x3b&(83e889d7)
83e889d1&f6456c01&&&&&&&&test&&&&byte&ptr&[ebp+6Ch],1
83e889d5&740c&&&&&&&&&&&&je&&&&&&nt!KiSystemServiceCopyArguments&(83e889e3)
83e889d7&3b&&&&cmp&&&&&esi,dword&ptr&[nt!MmUserProbeAddress&(83fb7850)]//参数块的位置&不得高于MmUserProbeAddress&这个定义了用户空间最大地址
83e889dd&0f832e020000&&&&jae&&&&&nt!KiSystemCallExit2+0xa5&(83e88c11)
nt!KiSystemServiceCopyArguments:
83e889e3&f3a5&&&&&&&&&&&&rep&movs&dword&ptr&es:[edi],dword&ptr&[esi]//复制用户空间参数到内核堆栈上
83e889e5&f6456c01&&&&&&&&test&&&&byte&ptr&[ebp+6Ch],1
83e889e9&7416&&&&&&&&&&&&je&&&&&&nt!KiSystemServiceCopyArguments+0x1e&(83e88a01)
83e889eb&648b0d&&mov&&&&&ecx,dword&ptr&fs:[124h]
83e889f2&8b3c24&&&&&&&&&&mov&&&&&edi,dword&ptr&[esp]
83e889f5&&&&&mov&&&&&dword&ptr&[ecx+13Ch],ebx
83e889fb&89b92c010000&&&&mov&&&&&dword&ptr&[ecx+12Ch],edi
83e88a01&8bda&&&&&&&&&&&&mov&&&&&ebx,edx
83e88a03&f40&&test&&&&byte&ptr&[nt!PerfGlobalGroupMask+0x8&(83f83788)],40h
83e88a0a&0f954512&&&&&&&&setne&&&byte&ptr&[ebp+12h]
83e88a0e&0f&&&&jne&&&&&nt!KiServiceExit2+0x179&(83e88d94)
83e88a14&ffd3&&&&&&&&&&&&call&&&&ebx//调用内核目标函数
nt!KiSystemServicePostCall:
83e88a16&f6456c01&&&&&&&&test&&&&byte&ptr&[ebp+6Ch],1
83e88a1a&7434&&&&&&&&&&&&je&&&&&&nt!KiSystemServicePostCall+0x3a&(83e88a50)
83e88a1c&8bf0&&&&&&&&&&&&mov&&&&&esi,eax
83e88a1e&ff&&&&call&&&&dword&ptr&[nt!_imp__KeGetCurrentIrql&(83e4c168)]
83e88a24&0ac0&&&&&&&&&&&&or&&&&&&al,al
83e88a26&0f852f030000&&&&jne&&&&&nt!KiServiceExit2+0x140&(83e88d5b)
83e88a2c&8bc6&&&&&&&&&&&&mov&&&&&eax,esi
83e88a2e&648b0d&&mov&&&&&ecx,dword&ptr&fs:[124h]
83e88a35&fff&&test&&&&byte&ptr&[ecx+134h],0FFh
83e88a3c&0f&&&&jne&&&&&nt!KiServiceExit2+0x15e&(83e88d79)
83e88a42&8b&&&&mov&&&&&edx,dword&ptr&[ecx+84h]
83e88a48&0bd2&&&&&&&&&&&&or&&&&&&edx,edx
83e88a4a&0f&&&&jne&&&&&nt!KiServiceExit2+0x15e&(83e88d79)
83e88a50&8be5&&&&&&&&&&&&mov&&&&&esp,ebp&//回到自陷框架
83e88a52&807d1200&&&&&&&&cmp&&&&&byte&ptr&[ebp+12h],0
83e88a56&0f&&&&jne&&&&&nt!KiServiceExit2+0x185&(83e88da0)
83e88a5c&648b0d&&mov&&&&&ecx,dword&ptr&fs:[124h]//使ecx指向当前线程的kthread
83e88a63&8b553c&&&&&&&&&&mov&&&&&edx,dword&ptr&[ebp+3Ch]//取出保存的TrapFrame框架
83e88a66&&&&&mov&&&&&dword&ptr&[ecx+128h],edx//恢复kthread里的Frame
nt!KiServiceExit:
83e88a6c&fa&&&&&&&&&&&&&&cli//关闭中断
83e88a6d&f6457202&&&&&&&&test&&&&byte&ptr&[ebp+72h],2
83e88a71&7506&&&&&&&&&&&&jne&&&&&nt!KiServiceExit+0xd&(83e88a79)
83e88a73&f6456c01&&&&&&&&test&&&&byte&ptr&[ebp+6Ch],1//执行APC的时机是在(系统调用、中断、或异常处理之后)从内核返回用户空间的途中&我们这里是系统调用返回的时候&如果先前模式是用户层&有用户APC请求正在等待执行(KTHREAD_PENDING_USER_APC是ApcState.KernelApcPending在KTHREAD数据结构中的位移)。&那么要提交apc请求(类似内核发送给用户层的”中断信号”&例如&用户层要异步读写文件&那么ReadFile调用完毕&继续执行别的去了&内核设备驱动程序收到io请求执行读写&读写完毕&就会通知用户程序&我已经读写完毕了&你需要暂时停止其他工作&先处理我读写后的数据&怎么通知用户层呢&就是APC回调了&每个线程2个队列&一个是内核apc队列(其中的回调函数是在内核)&一个是用户层apc队列(其中的回调函数在用户层)&&在这里读写文件&是用户层APC&执行用户apc前(每次只执行队列的第一个)&必须先把内核apc队列里的所有函数都执行完毕后再执行用户apc队列的函数&&如果是内核模式的apc&那么就只执行线程内核apc队列所有函数)
83e88a77&7467&&&&&&&&&&&&je&&&&&&nt!KiServiceExit+0x74&(83e88ae0)
83e88a79&648b1d&&mov&&&&&ebx,dword&ptr&fs:[124h]
83e88a80&f6430202&&&&&&&&test&&&&byte&ptr&[ebx+2],2
83e88a84&7408&&&&&&&&&&&&je&&&&&&nt!KiServiceExit+0x22&(83e88a8e)
83e88a86&50&&&&&&&&&&&&&&push&&&&eax
83e88a87&53&&&&&&&&&&&&&&push&&&&ebx
83e88a88&e8ce660a00&&&&&&call&&&&nt!KiCopyCounters&(83f2f15b)
83e88a8d&58&&&&&&&&&&&&&&pop&&&&&eax
83e88a8e&c6433a00&&&&&&&&mov&&&&&byte&ptr&[ebx+3Ah],0
83e88a92&807b5600&&&&&&&&cmp&&&&&byte&ptr&[ebx+56h],0
83e88a96&7448&&&&&&&&&&&&je&&&&&&nt!KiServiceExit+0x74&(83e88ae0)
83e88a98&8bdd&&&&&&&&&&&&mov&&&&&ebx,ebp
83e88a9a&894344&&&&&&&&&&mov&&&&&dword&ptr&[ebx+44h],eax
83e88a9d&c000&&mov&&&&&dword&ptr&[ebx+50h],3Bh
83e88aa4&c0&&mov&&&&&dword&ptr&[ebx+38h],23h
83e88aab&c0&&mov&&&&&dword&ptr&[ebx+34h],23h
83e88ab2&c0&&mov&&&&&dword&ptr&[ebx+30h],0
83e88ab9&b&&&&&&mov&&&&&ecx,1//APC&Level
83e88abe&ff155cc1e483&&&&call&&&&dword&ptr&[nt!_imp_KfRaiseIrql&(83e4c15c)]//提升irql&每个调用来自用户空间的内核函数执行完毕&都会提交APC(类似linux信号&发送给用户层&让用户层”中断”&)
83e88ac4&50&&&&&&&&&&&&&&push&&&&eax
83e88ac5&fb&&&&&&&&&&&&&&sti
83e88ac6&53&&&&&&&&&&&&&&push&&&&ebx
83e88ac7&6a00&&&&&&&&&&&&push&&&&0
83e88ac9&6a01&&&&&&&&&&&&push&&&&1
83e88acb&e8e53d0700&&&&&&call&&&&nt!KiDeliverApc&(83efc8b5)
83e88ad0&59&&&&&&&&&&&&&&pop&&&&&ecx
83e88ad1&ff&&&&call&&&&dword&ptr&[nt!_imp_KfLowerIrql&(83e4c158)]//不能主动降低irql&只能是升高irql后&再降低到原始irql&降低后&可能会发生线程切换&这个函数里面可能会执行DPC(调用KiDispatchInterrupt())最后会看看&KPCR得字段QuantumEnd是否为null&如果是&那么要切换线程了
83e88ad7&8b4344&&&&&&&&&&mov&&&&&eax,dword&ptr&[ebx+44h]
83e88ada&fa&&&&&&&&&&&&&&cli
83e88adb&eb9c&&&&&&&&&&&&jmp&&&&&nt!KiServiceExit+0xd&(83e88a79)
83e88add&8d4900&&&&&&&&&&lea&&&&&ecx,[ecx]
83e88ae0&8b54244c&&&&&&&&mov&&&&&edx,dword&ptr&[esp+4Ch]
83e88ae4&00&&mov&&&&&dword&ptr&fs:[0],edx
83e88aeb&8b4c2448&&&&&&&&mov&&&&&ecx,dword&ptr&[esp+48h]
83e88aef&648b&&mov&&&&&esi,dword&ptr&fs:[124h]
83e88af6&888e3a010000&&&&mov&&&&&byte&ptr&[esi+13Ah],cl
83e88afc&f744242cff23ffff&test&&&&dword&ptr&[esp+2Ch],0FFFF23FFh
83e88b04&0f857e000000&&&&jne&&&&&nt!KiSystemCallExit2+0x1c&(83e88b88)
83e88b0a&f200&test&&&&dword&ptr&[esp+70h],20000h
83e88b12&0f&&&&jne&&&&&nt!KiExceptionExit+0x134&(83e8954c)
83e88b18&66fff&&test&&&&word&ptr&[esp+6Ch],0FFF9h
83e88b1f&0f84b9000000&&&&je&&&&&&nt!KiSystemCallExit2+0x72&(83e88bde)
83e88b25&b&&&&cmp&&&&&word&ptr&[esp+6Ch],1Bh
83e88b2b&660fba64246c00&&bt&&&&&&word&ptr&[esp+6Ch],0
83e88b32&f5&&&&&&&&&&&&&&cmc
83e88b33&0f&&&&ja&&&&&&nt!KiSystemCallExit2+0x60&(83e88bcc)
83e88b39&&&&&&&cmp&&&&&word&ptr&[ebp+6Ch],8
83e88b3e&7405&&&&&&&&&&&&je&&&&&&nt!KiServiceExit+0xd9&(83e88b45)
83e88b40&8d6550&&&&&&&&&&lea&&&&&esp,[ebp+50h]
83e88b43&0fa1&&&&&&&&&&&&pop&&&&&fs
83e88b45&8d6554&&&&&&&&&&lea&&&&&esp,[ebp+54h]
83e88b48&5f&&&&&&&&&&&&&&pop&&&&&edi
83e88b49&5e&&&&&&&&&&&&&&pop&&&&&esi
83e88b4a&5b&&&&&&&&&&&&&&pop&&&&&ebx
83e88b4b&5d&&&&&&&&&&&&&&pop&&&&&ebp
83e88b4c&00&&cmp&&&&&word&ptr&[esp+8],80h
83e88b53&0f870f0a0000&&&&ja&&&&&&nt!KiExceptionExit+0x150&(83e89568)
83e88b59&83c404&&&&&&&&&&add&&&&&esp,4
83e88b5c&f000&test&&&&dword&ptr&[esp+4],1
nt!KiSystemCallExitBranch:
83e88b64&7506&&&&&&&&&&&&jne&&&&&nt!KiSystemCallExit2&(83e88b6c)
83e88b66&5a&&&&&&&&&&&&&&pop&&&&&edx
83e88b67&59&&&&&&&&&&&&&&pop&&&&&ecx/
83e88b68&9d&&&&&&&&&&&&&&popfd//出栈r3的eflags
83e88b69&ffe2&&&&&&&&&&&&jmp&&&&&edx//跳到edx返回地址
nt!KiSystemCallExit:
83e88b6b&cf&&&&&&&&&&&&&&iretd++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++&为什么内核中不能直接调用NtReadFile()呢?因为一方面NtReadFile不是导出函数 另外就是 调用这些函数 需要系统堆栈上有框架 但是内核中直接调用的话 肯定没有为本次调用的框架存在 可能是其他框架 比如自陷框架 中断异常框架 所以导致直接调用NtReadFile出错 可以通过调用ZwReadFile()调用以下是x86的nt!ZwReadFile:
83e874cc&b&&&&&&mov&&&&&eax,111h//因为是内核直接调用&所以无须保存各个寄存器
83e874d1&8d542404&&&&&&&&lea&&&&&edx,[esp+4]//使edx指向堆栈上的参数快
83e874d5&9c&&&&&&&&&&&&&&pushfd&&&//&eflags
83e874d6&6a08&&&&&&&&&&&&push&&&&8//cs
83e874d8&e&&&&&&call&&&&nt!KiSystemService&(83e8880e)//通过调用它来形成框架
83e874dd&c22400&&&&&&&&&&ret&&&&&24h&以下是x64的nt!ZwReadFile:
fffff800`03c6f6e0&488bc4&&&&&&&&&&mov&&&&&rax,rsp
fffff800`03c6f6e3&fa&&&&&&&&&&&&&&cli
fffff800`03c6f6e4&4883ec10&&&&&&&&sub&&&&&rsp,10h
fffff800`03c6f6e8&50&&&&&&&&&&&&&&push&&&&rax
fffff800`03c6f6e9&9c&&&&&&&&&&&&&&pushfq
fffff800`03c6f6ea&6a10&&&&&&&&&&&&push&&&&10h
fffff800`03c6f6ec&488d05dd310000&&lea&&&&&rax,[nt!KiServiceLinkage&(fffff800`03c728d0)]
fffff800`03c6f6f3&50&&&&&&&&&&&&&&push&&&&rax
fffff800`03c6f6f4&b&&&&&&mov&&&&&eax,3
fffff800`03c6f6f9&e&jmp&&nt!KiServiceInternal&(fffff800`03c76000)//KiServiceLinkage&和KiServiceInternal&都是初始化系统服务的里面会调用KiSystemServiceStart-&KiSystemServiceRepeat(选择ssdt&还是shadow&ssdt执行调用)-&KiSystemServiceExit(退出调用)
fffff800`03c6f6fe&6690&&&&&&&&&&&&xchg&&&&ax,ax&&& & &&&最近身体出问题了 所以进度很慢 &希望大家多多支持&
上传的附件:
(122.19kb,54次下载)
本主题帖已收到 1 次赞赏,累计¥1.00
支付方式:
最新回复 (9)
支持分享,学习一下
排版有点乱,最好把代码用代码格式刷一遍,这样看起来清楚一点。
同上& & 现在完全可以用那个代码格式化一下& 看着舒服些&
mark写的很好
哥们注意身体!!!非常感谢您分享!!!很不错的文章。佩服您的专研精神。
支持支持!好牛逼
1.请先关注公众号。
2.点击菜单"更多"。
3.选择获取下载码。}

我要回帖

更多关于 android x86 for pc 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信