IDT hook KiTrap03
关于idt的基本知识就不进行赘述了,先看一个例子
- 0x1000: mov eax,x1006: Int ;------->进入内核,找到中断处理例程KiTrap03
- 0x1007: Mov eax,
这段代码执行,触发3号中断,然后开始执行KiTrap03例程,要知道,执行完中断以后还是要回到原来的程序处继续执行的,也就是我们这的Mov eax, 1的指令,显然,发生中断时的寄存器环境就要被保存,便于之后的恢复程序运行,这里,就出现了一个结构_KTRAP_FRAME,陷阱帧。
- kd> dt _KTRAP_FRAME
- nt!_KTRAP_FRAME
- +0x000 DbgEbp : Uint4B
- +0x004 DbgEip : Uint4B
- +0x008 DbgArgMark : Uint4B
- +0x00c DbgArgPointer : Uint4B
- +0x010 TempSegCs : Uint2B
- +0x012 Logging : UChar
- +0x013 Reserved : UChar
- +0x014 TempEsp : Uint4B
- +0x018 Dr0 : Uint4B
- +0x01c Dr1 : Uint4B
- +0x020 Dr2 : Uint4B
- +0x024 Dr3 : Uint4B
- +0x028 Dr6 : Uint4B
- +0x02c Dr7 : Uint4B
- +0x030 SegGs : Uint4B
- +0x034 SegEs : Uint4B
- +0x038 SegDs : Uint4B
- +0x03c Edx : Uint4B
- +0x040 Ecx : Uint4B
- +0x044 Eax : Uint4B
- +0x048 PreviousPreviousMode : Uint4B
- +0x04c ExceptionList : Ptr32 _EXCEPTION_REGISTRATION_RECORD
- +0x050 SegFs : Uint4B
- +0x054 Edi : Uint4B
- +0x058 Esi : Uint4B
- +0x05c Ebx : Uint4B
- +0x060 Ebp : Uint4B
- +0x064 ErrCode : Uint4B
- +0x068 Eip : Uint4B //硬件自动填充
- +0x06c SegCs : Uint4B //硬件自动填充
- +0x070 EFlags : Uint4B //硬件自动填充
- //后面都是可选的,只有当我们运行的程序处于虚拟86模式异常才会有
- +0x074 HardwareEsp : Uint4B
- +0x078 HardwareSegSs : Uint4B
- +0x07c V86Es : Uint4B
- +0x080 V86Ds : Uint4B
- +0x084 V86Fs : Uint4B
- +0x088 V86Gs : Uint4B
整个陷阱帧结构记录中断发生时的寄存器环境,其中,结构体最后面的几个成员只有运行于虚拟86模式下才会存在,而Eip,SegCs和EFlags三个成员由硬件自动填充,然后剩下的成员才是由KiTrap03自己构建的陷阱帧,我们可以分析下KiTrap03的代码,由于在wrk中只有asm文件,没有C源代码,用ida进行分析
- .text:00436C50 _KiTrap03 proc near ; DATA XREF: INIT:0077317Co
- .text:00436C50
- .text:00436C50 var_2= word ptr -
- .text:00436C50 arg_4= dword ptr
- .text:00436C50
- .text:00436C50 push ; Trap_frame.Errcode
- .text:00436C52 mov [esp++var_2], ; Trap_frame.Errcode = 0
- .text:00436C59 push ebp ; Trap_frame.Ebp
- .text:00436C5A push ebx ; Trap_frame.Ebx
- .text:00436C5B push esi ; Trap_frame.Esi
- .text:00436C5C push edi ; Trap_frame.Edi
- .text:00436C5D push fs ; Trap_frame.SegFs
- .text:00436C5F mov ebx, 30h
- .text:00436C64 mov fs, bx
- .text:00436C67 mov ebx, large fs: ; fs对应处理器相关的_KPCR结构,kpcr,那么得到的是
- .text:00436C67 ; kpcr.NtTib.ExceptionList
- .text:00436C6E push ebx ; Trap_frame.ExceptionList
- .text:00436C6F sub esp, ; Trap_frame.PreviousPreviousMode,在后面填充
- .text:00436C72 push eax ; Trap_frame.Eax
- .text:00436C73 push ecx ; Trap_frame.Ecx
- .text:00436C74 push edx ; Trap_frame.Edx
- .text:00436C75 push ds ; Trap_frame.SegDs
- .text:00436C76 push es ; Trap_frame.SegEs
- .text:00436C77 push gs ; Trap_frame.SegGs
- .text:00436C79 mov ax, 23h ; ???
- .text:00436C7D sub esp, 30h ; 继续增大栈空间,刚好是整个Trap_Frame的大小
- .text:00436C80 mov ds, ax ; ???
- .text:00436C83 mov es, ax
- .text:00436C86 mov ebp, esp ; ebp指向Trap_frame
- .text:00436C88 test [esp+68h+arg_4], 20000h ; Trap_frame.EFlags,0x2000代表EFLAGS_V86_MASK,
- .text:00436C88 ; 标记虚拟86模式
- .text:00436C90 jnz short V86_kit3_a ; 如果是虚拟86模式跳转
- .text:00436C92
- .text:00436C92 loc_436C92: ; CODE XREF: V86_kit3_a+25j
- .text:00436C92 mov ecx, large fs:124h ; ecx = CurrentThread
- .text:00436C92 ; +0x004 CurrentThread : Ptr32 _KTHREAD 当前线程 ecx
- .text:00436C99 cld
- .text:00436C9A and dword ptr [ebp+2Ch], ; Trap_frame.Dr7清零
- .text:00436C9E test byte ptr [ecx+], 0DFh
- .text:00436CA2 jnz Dr_kit3_a
- .text:00436CA8
- .text:00436CA8 loc_436CA8: ; CODE XREF: Dr_kit3_a+Dj
- .text:00436CA8 ; Dr_kit3_a+79j
- .text:00436CA8 mov ebx, [ebp+60h]
- .text:00436CAB mov edi, [ebp+68h]
- .text:00436CAE mov [ebp+0Ch], edx ; Trap_frame.DbgArgPointer = edx
- .text:00436CB1 mov dword ptr [ebp+], 0BADB0D00h ; Trap_frame.DbgArgMark = 0BADB0D00h
- .text:00436CB8 mov [ebp+], ebx ; Trap_frame.DbgEbp = kTrap_frame.Ebp
- .text:00436CBB mov [ebp+], edi ; Trap_frame.DbgEip = kTrap_frame.Eip
- .text:00436CBE cmp ds:_PoHiberInProgress,
- .text:00436CC5 jnz short loc_436CCE
- .text:00436CC7 lock inc ds:_KiHardwareTrigger
- .text:00436CCE
- .text:00436CCE loc_436CCE: ; CODE XREF: _KiTrap03+75j
- .text:00436CCE mov eax,
- .text:00436CD3
- .text:00436CD3 loc_436CD3: ; CODE XREF: _KiDebugService+7Aj
- .text:00436CD3 test byte ptr [ebp+72h],
- .text:00436CD7 jnz short loc_436D08
- .text:00436CD9 test byte ptr [ebp+6Ch], ; CS 最后一位,判断是否为UserMode
- .text:00436CDD jnz short loc_436CE7 ; 如果是UserMode,跳转
- .text:00436CDF test byte ptr [ebp+71h], ; 判断Eflags.IF位是否存在
- .text:00436CE3 jz short loc_436CEF
- .text:00436CE5 jmp short loc_436CEE
- .text:00436CE7 ; ---------------------------------------------------------------------------
- .text:00436CE7
- .text:00436CE7 loc_436CE7: ; CODE XREF: _KiTrap03+8Dj
- .text:00436CE7 cmp word ptr [ebp+6Ch], 1Bh
- .text:00436CEC jnz short loc_436D08
- .text:00436CEE
- .text:00436CEE loc_436CEE: ; CODE XREF: _KiTrap03+95j
- .text:00436CEE ; _KiTrap03+C9j
- .text:00436CEE sti ; IF标志位存在
- .text:00436CEF
- .text:00436CEF loc_436CEF: ; CODE XREF: _KiTrap03+93j
- .text:00436CEF ; _KiTrap03+D6j
- .text:00436CEF mov esi, ecx ; esi=CurrentThread
- .text:00436CF1 mov edi, edx
- .text:00436CF3 mov edx, eax
- .text:00436CF5 mov ebx, [ebp+68h] ; ebx = kTrap_frame.Eip
- .text:00436CF8 dec ebx ; "eip-1"是因为int 3本身占一个字节
- .text:00436CF9 mov ecx, ; ???在下层函数中会用到,到时候就知道了
- .text:00436CFE mov eax, 80000003h ; 异常类型(STATUS_BREAKPOINT)
- .text:00436D03 call CommonDispatchException ; 处理异常
- .text:00436D08
- .text:00436D08 loc_436D08: ; CODE XREF: _KiTrap03+87j
- .text:00436D08 ; _KiTrap03+9Cj
- .text:00436D08 mov ebx, large fs:124h
- .text:00436D0F mov ebx, [ebx+50h]
- .text:00436D12 cmp dword ptr [ebx+148h],
- .text:00436D19 jz short loc_436CEE
- .text:00436D1B push
- .text:00436D1D call _Ki386VdmReflectException_A@4 ; Ki386VdmReflectException_A(x)
- .text:00436D22 test ax, 0FFFFh
- .text:00436D26 jz short loc_436CEF
- .text:00436D28 jmp Kei386EoiHelper@0
- .text:00436D28 _KiTrap03 endp
很明显,在KiTrap03中没有进行太多的处理,只是判断是否是虚拟86模式来构建了一个不同的陷阱帧结构,之后调用了CommonDispatchException 函数来处理异常。
在虚拟86模式下将会跳转到V86_kit3_a,我们可以看下实现
- .text:00436C28 V86_kit3_a proc near ; CODE XREF: _KiTrap03+40j
- .text:00436C28 mov eax, [ebp+84h]
- .text:00436C2E mov ebx, [ebp+88h]
- .text:00436C34 mov ecx, [ebp+7Ch]
- .text:00436C37 mov edx, [ebp+80h]
- .text:00436C3D mov [ebp+50h], ax ; Trap_frame.SegFs = Trap_frame.V86Fs
- .text:00436C41 mov [ebp+30h], bx ; Trap_frame.SegGs = Trap_frame.V86Gs
- .text:00436C45 mov [ebp+34h], cx ; Trap_frame.SegEs = Trap_frame.V86Es
- .text:00436C49 mov [ebp+38h], dx ; Trap_frame.SegDs = Trap_frame.V86Ds
- .text:00436C4D jmp short loc_436C92
- .text:00436C4D V86_kit3_a endp
可以看到V86_kit3_a中没有进行处理,只是将陷阱帧中保存的寄存器的值对应为虚拟86模式特有的值。
然后跟入CommonDispatchException 函数
- .text:0043641C CommonDispatchException proc near ; CODE XREF: _KiTrap00-253p
- .text:0043641C ; _KiTrap00-247p _KiTrap00-23Bp
- .text:0043641C ; _KiTrap03+B3p _KiTrap0E+21Ap
- .text:0043641C ; sub_671B78+24p
- .text:0043641C
- .text:0043641C var_50= dword ptr -50h
- .text:0043641C var_4C= dword ptr -4Ch
- .text:0043641C var_48= dword ptr -48h
- .text:0043641C var_44= dword ptr -44h
- .text:0043641C var_40= dword ptr -40h
- .text:0043641C var_3C= byte ptr -3Ch
- .text:0043641C
- .text:0043641C sub esp, 50h ; EXCEPTION_RECORD结构空间,ExceptionRecord
- .text:0043641F mov [esp+50h+var_50], eax ; eax是上层调用设置的错误码,这里是
- .text:0043641F ; ExceptionRecord->ExceptionCode = eax
- .text: xor eax, eax
- .text: mov [esp+50h+var_4C], eax ; ExceptionRecord->ExceptionFlags = 0
- .text: mov [esp+50h+var_48], eax ; ExceptionRecord->ExceptionRecord = 0
- .text:0043642C mov [esp+50h+var_44], ebx ; ebx是上层调用设置的异常发生处地址,
- .text:0043642C ; ExceptionRecord->ExceptionAddress = ebx
- .text: mov [esp+50h+var_40], ecx ; ExceptionRecord->NumberParameters = ecx
- .text: ; 表示ExceptionRecord->ExceptionInformation数组的数量
- .text: cmp ecx, ; ExceptionRecord->NumberParameters为零跳转
- .text: jz short loc_436445
- .text: lea ebx, [esp+50h+var_3C] ; ebx = ExceptionRecord->ExceptionInformation
- .text:0043643D mov [ebx], edx ; 开始填充ExceptionInformation的信息
- .text:0043643F mov [ebx+], esi
- .text: mov [ebx+], edi
- .text:
- .text: loc_436445: ; CODE XREF: CommonDispatchException+1Bj
- .text: mov ecx, esp ; ecx = ExceptionRecord
- .text: test byte ptr [ebp+72h], ; ebp还是指向TrapFrame,TrapFrame->EFlags,
- .text: ; 这里是EFlags的高2字节,判断是否为虚拟86模式
- .text:0043644B jz short loc_436454
- .text:0043644D mov eax, 0FFFFh ; ????
- .text: jmp short loc_436457
- .text: ; ---------------------------------------------------------------------------
- .text:
- .text: loc_436454: ; CODE XREF: CommonDispatchException+2Fj
- .text: mov eax, [ebp+6Ch] ; eax = TrapFrame->SegCs
- .text:
- .text: loc_436457: ; CODE XREF: CommonDispatchException+36j
- .text: and eax, ; Cs的低两位得到处理器模式
- .text:0043645A push ; FirstChance
- .text:0043645C push eax ; PreviousMode
- .text:0043645D push ebp ; TrapFrame
- .text:0043645E push ; ExceptionFrame
- .text: push ecx ; void *
- .text: call _KiDispatchException@20 ; 对异常进行分发处理
- .text: mov esp, ebp ; 修正esp,然后执行退出操作
- .text: jmp Kei386EoiHelper@0
- .text: CommonDispatchException endp
可以看到CommonDispatchException也没有进行处理,只是构建了一个ExceptionRecord的结构体,就对异常进行了分发处理,进入了熟悉的KiDispatchException函数。
了解了陷阱帧的构建,再看idt表的基本结构,每个CPU的核心都有自己的idt表,
- typedef struct _IDTR
- {
- USHORT limit; //整个表所占内存大小
- ULONG base; //IDT表项起始地址
- }IDTR,*PIDTR;
在我的虚拟机上 limit= 0x7ff (包含0) 0x800 = 2048 Entry每项大小8字节,就2048/8 = 256 成员,idt表有256个例程
可以使用kd> !idt -a 命令来查看idt表的详细信息,可以发现就是有256个例程
idt表中的每一项对应一种中断处理例程,结构体如下,我们最关心的是LowOffset和HiOffset这两个成员,他们组成了处理例程地址的高16位和低16位
- typedef struct _IDTENTRY
- {
- unsigned short LowOffset;
- unsigned short selector;
- unsigned char retention:;
- unsigned char zero1:;
- unsigned char gate_type:;
- unsigned char zero2:;
- unsigned char interrupt_gate_size:;
- unsigned char zero3:;
- unsigned char zero4:;
- unsigned char DPL:;
- unsigned char P:;
- unsigned short HiOffset;
- } IDTENTRY,*PIDTENTRY;
利用MAKELONG 的宏,可以得到处理例程的真正地址
- #define MAKELONG(a, b) ((LONG)(((WORD)(((DWORD_PTR)(a)) & 0xffff)) | ((DWORD)((WORD)(((DWORD_PTR)(b)) & 0xffff))) << 16))
idt表的获得可以通过sidt指令或者时_KPCR中的成员获得,在内核态fs段寄存器是指向_KPCR结构。
- kd> dt _kpcr
- ......
- +0x038 IDT ; Ptr32 _KIDTENTRY
- ......
下面的代码打印了每次触发INT 3断点的地址,可以用OD下普通的断点进行测试,可以打印出断点的地址。
- ULONG_PTR g_OrigKiTrap03;
- KIRQL Irql;
- _declspec(naked) void NewKiTrap03()
- {
- __asm
- {
- //测试
- //jmp g_OrigKiTrap03
- //构建Trap03的异常帧
- //保存现场环境,和原始Trap03一样
- push ;ErrorCode
- push ebp
- push ebx
- push esi
- push edi
- push fs
- mov ebx,30h
- mov fs,bx
- mov ebx,dword ptr fs:[]
- push ebx
- sub esp,
- push eax
- push ecx
- push edx
- push ds
- push es
- push gs
- sub esp,30h //esp此时就指向陷阱帧
- push esp //FilterExceptionInfo自己清理了
- call FilterExceptionInfo //过滤函数
- add esp , 0x30
- pop gs
- pop es
- pop ds
- pop edx
- pop ecx
- pop eax
- add esp ,
- pop ebx
- pop fs
- pop edi
- pop esi
- pop ebx
- pop ebp
- add esp , 0x4
- jmp g_OrigKiTrap03
- }
- }
- VOID __stdcall FilterExceptionInfo(PX86_KTRAP_FRAME pTrapFrame)
- {
- //eip的值减一过int3,汇编代码分析中dec,
- DbgPrint("Eip:%x\r\n",(pTrapFrame->Eip)-);
- }
- NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryString)
- {
- NTSTATUS Status = STATUS_SUCCESS;
- IDTR Idtr;
- PIDTENTRY pIdtArray = NULL;
- ULONG_PTR Index = ;
- DriverObject->DriverUnload = UnloadDriver;
- __asm sidt Idtr
- //虚拟机是单核的,只用一个就可以了
- if(KeGetIdt(&pIdtArray))
- {
- DbgPrint("%x---%x\r\n",Idtr.base,Idtr.limit);
- for (Index =;Index<(Idtr.limit+)/sizeof(IDTENTRY);Index++)
- {
- DbgPrint("TrapHandle[%d]:%x\r\n",Index,MAKELONG(pIdtArray[Index].LowOffset,pIdtArray[Index].HiOffset));
- }
- g_OrigKiTrap03 = MAKELONG(pIdtArray[].LowOffset,pIdtArray[].HiOffset);
- WPOFF();
- pIdtArray[].LowOffset = (ULONG_PTR)NewKiTrap03 & 0xFFFF; //低16位
- pIdtArray[].HiOffset = (ULONG_PTR)NewKiTrap03 >> ; //高16位
- WPON();
- }
- //limit 0x7ff (包含0) 0x800 = 2048 Entry每项大小8字节,就2048/8 = 256 成员
- //!idt -a 0ff = 256
- //MAKELONG
- //#define MAKELONG(a, b) ((LONG)(((WORD)(((DWORD_PTR)(a)) & 0xffff)) | ((DWORD)((WORD)(((DWORD_PTR)(b)) & 0xffff))) << 16))
- return Status;
- }
- BOOLEAN KeGetIdt(PIDTENTRY *pIdtArray)
- {
- ULONG Index,Affinity,CurrentAffinity;
- pfnKESETAFFINITYTHREAD fnpKeSetAffinityThread;
- UNICODE_STRING usFuncName;
- PIDTENTRY pIdtEntry;
- RtlInitUnicodeString(&usFuncName,L"KeSetAffinityThread");
- fnpKeSetAffinityThread = (pfnKESETAFFINITYTHREAD)MmGetSystemRoutineAddress(&usFuncName);
- if (fnpKeSetAffinityThread==)
- {
- return FALSE;
- }
- Affinity = KeQueryActiveProcessors();
- //KeQueryActiveProcessors获取处理器相关的位图
- //(这里的位图可以理解为个数,比如返回1代表一个处理器,返回3表示两个处理器,返回7表示三个处理器,依此类推。
- //也就是说从有多少个处理器,那么Affinity的值就会从低位到高位依此填充多少位)
- CurrentAffinity = ;
- Index = ;
- while(Affinity)
- {
- //下面只是个简单的算法,使当前线程运行到不同的处理器上
- Affinity &= ~CurrentAffinity;
- fnpKeSetAffinityThread(PsGetCurrentThread(),(KAFFINITY)CurrentAffinity);
- CurrentAffinity <<= ;
- __asm{
- push eax
- mov eax,fs:[0x38]
- mov pIdtEntry,eax
- pop eax
- }
- //得到我们要的东西
- pIdtArray[Index] = pIdtEntry;
- Index++;
- }
- return TRUE;
- }
- VOID WPOFF()
- {
- ULONG_PTR cr0 = ;
- Irql = KeRaiseIrqlToDpcLevel();
- cr0 =__readcr0();
- cr0 &= 0xfffffffffffeffff;
- __writecr0(cr0);
- }
- VOID WPON()
- {
- ULONG_PTR cr0=__readcr0();
- cr0 |= 0x10000;
- __writecr0(cr0);
- KeLowerIrql(Irql);
- }
- VOID UnloadDriver(PDRIVER_OBJECT DriverObject)
- {
- //恢复
- PIDTENTRY pIdtEntry;
- if (g_OrigKiTrap03 && KeGetIdt(&pIdtEntry))
- {
- WPOFF();
- pIdtEntry[].LowOffset = g_OrigKiTrap03 & 0xFFFF;
- pIdtEntry[].HiOffset = g_OrigKiTrap03 >> ;
- WPON();
- }
- }
IDT hook KiTrap03的更多相关文章
- Windows xp下IDT Hook和GDT的学习
一.前言 对于IDT第一次的认知是int 2e ,在系统调用的时候原来R3进入R0的方式就是通过int 2e自陷进入内核,然后进入KiSystemService函数,在根据系统服务调用号调用系统服 ...
- IDT HOOK思路整理
IDT(中断描述符表)分为IRQ(真正的硬件中断)和软件中断(又叫异常). HOOK的思路为,替换键盘中断处理的函数地址为自己的函数地址.这样在键盘驱动和过滤驱动之前就可以截获键盘输入. 思路确定之后 ...
- RootKit学习之 IDT Hook
0x00 前言 IDT(Interrupt Descriptor Table)中断描述符表,中断就是停下现在的活动,去完成新的任务.一个中断可以起源于软件或硬件.比如,出现页错误,调用IDT中的0x ...
- IDTHook 深入学习
在之前的一篇文章中介绍了替换IDT向量表中的地址来达到Hook的目的 IDT hook KiTrap03 但是这样很容易就可以被检测了.接下来要学习就是通过patch GDT来达到Hook IDT的目 ...
- IDT系统中断描述表以及绕过Xurtr检测的HOOK姿势
什么是中断? 指当出现需要时,CPU暂时停止当前程序的执行转而执行处理新情况的程序和执行过程.即在程序运行过程中,系统出现了一个必须由CPU立即处理的情况,此时,CPU暂时中止程序的执行转而处理这个 ...
- hook技术分类
1.HOOK SERVICE TABLE:HOOK SSDT 这种方法对于拦截 NATIVE API 来说用的比较多. SSDT hook,一句话——Windows把需要调用的内核API地址全都存在了 ...
- Windows Dll Injection、Process Injection、API Hook、DLL后门/恶意程序入侵技术
catalogue 1. 引言2. 使用注册表注入DLL3. 使用Windows挂钩来注入DLL4. 使用远程线程来注入DLL5. 使用木马DLL来注入DLL6. 把DLL作为调试器来注入7. 使用c ...
- hook 9大类
HOOK技术主要分为两大类,一是内核层HOOK,一是用户层HOOK. 用户层HOOK也就是在ring3环境下hook kenerl32.dll.User3.dll.Gui32.dll.Advapi.d ...
- Hook基本知识
一.什么是HOOK(钩子) Windows系统,建立在事件驱动机制上,就是整个系统都是通过消息传递实现的.hook(钩子)是一种特殊的消息处理机制,它可以监视系统或者进程中的各种事件消息,截获发往目标 ...
随机推荐
- iOS App Launch Option
iOS 程序启动时总会调用application:didFinishLaunchingWithOptions:,其中第二个参数launchOptions为NSDictionary类型的对象,里面存储有 ...
- wordpress 为文章内容添加自动过滤,例如为出站链接添加nofollow,也可以将淘宝客链接转换。。
做seo的都明白,反向链接对与网站的优化有着很重要的作用,是搜索引擎给网站排名的一个重要因素.为了添加反向链接,SEO作弊者会在论坛和博客等大量发布带无关链接的 内容.这些垃圾链接的存在给搜索引擎对网 ...
- Linux android开发环境问题:Unexcepted exception:cannot run program "android-sdk-linux/platfor-tools/adb" :err=2,No such file or directory.
出现这个问题的原因: 我的linux是64位 ,而adb目前只有32位的,所以要安装运行32的环境. 不同的linux系统需要安装的不同: 我的Centos 解决方案如下 其他linux操作系统(参 ...
- ASP运行流程(主要的类笔记)
个人笔记:参考汤姆大叔的MVC之前那些事系列整理 client端发送页面请求,被IIS的某个进程截获,它根据申请的页面后缀(.aspx)不同,调用不同的页面处理程序(.asp->asp.dll ...
- EF6 在原有数据库中使用 CodeFirst 总复习(二、新的需求,简单修改原有表)
一.为当前实体模型启用数据迁移 基础搭建好了,也就是原有的数据库有了,原有数据库的实体对象也有了,但生成的上下文中并没有标记当前数据库是否已经存在,当前实体是否修改过(以前版本好像有标记的),所以,要 ...
- [网络配置相关]——ifconfig命令、ip命令、route命令
ifconfig命令 1. 查看已被激活的网卡的详细信息 # ifconfig eth0 Link encap:Ethernet HWaddr 00:30:67:F2:10:CF inet addr: ...
- JAVA标签的使用跳出循环
public static void main(String args[]) { int i=10,j=10; outer: while (i > 0) { inner: while (j &g ...
- 移植net-snmp到开发板(mini210)
1.安装交叉编译工具arm-linux-gcc 2.下载net-snmp源码安装包 3.解压安装包 4../configure --build=i686-linux --host=arm-linux ...
- xml之Schema架构
1.什么是Schema架构 2.Schema文档结构 3.Schema元素类型 1>element元素 <!--简单数据:类型--> <xs:element name=&qu ...
- 【BZOJ】【2480】【SPOJ 3105】Mod
扩展BSGS Orz zyf……然而他的题解对AC大神的题解作了引用……而坑爹的百度云……呵呵了... 扩展BSGS模板题 /************************************* ...