(25)2-9-9-12分页(下)
一、2-9-9-12分页结构
PDPTE,PDE,PTE都占8字节。
二、页目录指针表项 Page-Directory-Point-Table Entry
PDPTE的12-35位存储了页目录表基址的高24位,低12位补零。物理地址共占36位,接下来介绍的PDE,PTE均是如此。
PCD, PWT等属性等学到TLB才知道是干嘛的。
三、页目录项 PDE
从上图可以看出,PS位=1时,PDE直接指向大物理页,其中,物理页偏移由线性地址的剩余21位(32-2-9=21)构成,由此推出大物理页占2^21=2MB;PS=0时,PDE指向页表。
解释一下G位,G=1表示这是全局页,是多个进程共享的,这种页是通过 CreateFileMapping 申请的。与之对应的,G=0就是进程独享的物理页,这种页是通过 VirtualAlloc 分配的。
G=1,即为全局页,进程(CR3)切换时,TLB中的记录不会被刷新。
最后解释一下最高位(图中没有标出的保留位),称为XD位或者NX位,当最高位置1,表示这个物理页不能当成代码执行。XD位是PDE和PTE都有的,PDE或PTE的XD位只要有一个是1,这个物理页就不能执行。
四、页表项 PTE
属性部分和10-10-12差不多,没什么新东西,注意物理页基址是36位,最高位是XD位即可。
五、给0线性地址挂上物理页
写一个测试程序:
// ReadWriteNULL_2-9-9-12.cpp : Defines the entry point for the console application.
//#include "stdafx.h"int _tmain(int argc, _TCHAR* argv[])
{char data[0x1000] = {0};int *p = NULL;printf("可用的物理页基址:%p\n", data);printf("请在windbg中给NULL挂物理页.\n");getchar(); // windbg...// 读写NULL*p = 0x20201008;printf("*NULL = %x\n", *p);getchar();return 0;
}
让程序跑起来:
上节课已经手动拆过线性地址啦,所以今天就用 !vtop 偷懒了。
查CR3
!process 0 0
CR3=134c03e0
拆NULL
kd> !vtop 134c03e0 0
X86VtoP: Virt 00000000, pagedir 134c03e0
X86VtoP: PAE PDPE 134c03e0 - 0000000011046001
X86VtoP: PAE PDE 11046000 - 000000000f4e1067
X86VtoP: PAE PTE f4e1000 - 0000000000000000
X86VtoP: PAE zero PTE
Virtual address 0 translation fails, error 0xD0000147.
拆0x12ef60
kd> !vtop 134c03e0 12ef60
X86VtoP: Virt 0012ef60, pagedir 134c03e0
X86VtoP: PAE PDPE 134c03e0 - 0000000011046001
X86VtoP: PAE PDE 11046000 - 000000000f4e1067
X86VtoP: PAE PTE f4e1970 - 800000001d6b5067
X86VtoP: PAE Mapped phys 1d6b5f60
Virtual address 12ef60 translates to physical address 1d6b5f60.
挂物理页(没有!eq指令??)
!ed f4e1000 1d6b5067
!ed f4e1004 80000000
改好了,执行剩余代码:
实验成功。
六、修改页属性,实现应用层读写高2G内存地址
编写一个程序,读写0x8003f048.
// ReadWriteH2G_2-9-9-12.cpp : Defines the entry point for the console application.
//#include "stdafx.h"
#include <windows.h>int _tmain(int argc, _TCHAR* argv[])
{printf("请在windbg修改8003f048的U/S位.\n");getchar();printf("%08x\n", *(PDWORD)0x8003f048); // 读*(PDWORD)0x8003f048 = 0x12345678; // 写printf("%08x\n", *(PDWORD)0x8003f048); // 读getchar();return 0;
}
让程序跑起来。
查CR3
!process 0 0
CR3 = 12100420
拆8003f048
!vtop 12100420 8003f048
kd> !vtop 12100420 8003f048
X86VtoP: Virt 8003f048, pagedir 12100420
X86VtoP: PAE PDPE 12100430 - 00000000044c8001
X86VtoP: PAE PDE 44c8000 - 0000000000b5a163
X86VtoP: PAE PTE b5a1f8 - 000000000003f163
X86VtoP: PAE Mapped phys 3f048
Virtual address 8003f048 translates to physical address 3f048.
改U/S位,和PTE的G位
G=1时,程序会崩,只有G=0才能成功。
简单解释一下G位:
PDE中,只有PS=1(大页)时,G才有效。
G位是全局页的意思,G=1时,这个线性地址对应的页是全局页,进程切换时,对应的TLB不会改变。多个进程的高2G数据大部分都是相同的,我们不希望在切换进程时对这部分TLB做多余的刷新,所以需要设置G=1以提高效率。
回到本文,我们已经知道PDE的PS=0,所以我们不用管PDE的G。关键是PTE的G,为什么要改成0呢?因为线性地址 0x8003f048 默认是G=1,它在CPU中有TLB缓存。
我们修改了 0x8003f048 的PTE的U/S位,但是因为G=1,在CPU中有缓存,访问线性地址时优先读取TLB缓存,而缓存中的ATTR并没有改变,所以我们对U/S的修改是无效的。即使用 !ed 指令改了U/S,我们的应用层代码试图访问 0x8003f048 时,用的仍然是旧的属性,U/S仍然是0.
更多关于TLB和G位的知识,请看后续的TLB专题博客。
!ed 44c8000 00b5a167
!ed b5a1f8 0003f067
执行剩余的代码:
七、逆向分析MmIsAddressValid函数
首先给出我自己画的示意图:
根据示意图,0xC000000是第一张页表的线性地址,0xC0600000是第一张页目录表的线性地址。
结合示意图,理解下面的公式:
2-9-9-12
PDPTI-PDI-PTI-OFFSET 公式:
pPDE = 0xc0600000 + (PDPTI*4KB) + (PDI*8)
pPTE = 0xc0000000 + (PDPTI*2MB) + (PDI*4KB) + (PTI*8) 更高效的公式(MmIsAddressValid是这么干的)
pPDE = 0xc0600000 + ((addr >> 18) & 0x3ff8)
pPTE = 0xc0000000 + ((addr >> 9) & 0x7ffff8)
解释:
0xc0600000 是第一张页目录表,0xc0600000 + (PDPTI * 4KB) 就是找线性地址对应的页目录表,再加上(PDI * 8)就找到了对应的PDE。
0xc0000000 是第一张页表,0xc0000000 + (PDPTI * 2MB) 就是找线性地址对应的2MB页表的基址,然后加上 (PDI4KB) 就是对应的页表,最后再加上(PTI8)就找到了PTE。
理解了2-9-9-12的映射结构,再来分析 MmIsAddressValid 函数就比较容易了。
该函数为了提高效率,移位看起来比较费脑,但只要理解了我上面画的示意图和那些公式,分析起来应该就没什么问题了。
代码中有一些莫名其妙的语句,比如:
.text:004399A1 mov [ebp+var_4], eax.text:004399B7 push 0
.text:004399B9 mov [ebp+var_8], edx
.text:004399BC pop eax
猜测是因为编程使用的是C语言,所以生成了一些冗余的代码。
分析前:
---------------------------------------------------------------------------
.text:0043997A align 10h
.text:00439980 ; Exported entry 685. MmIsAddressValid
.text:00439980
.text:00439980 ; =============== S U B R O U T I N E =======================================
.text:00439980
.text:00439980 ; Attributes: bp-based frame
.text:00439980
.text:00439980 ; BOOLEAN __stdcall MmIsAddressValid(PVOID VirtualAddress)
.text:00439980 public _MmIsAddressValid@4
.text:00439980 _MmIsAddressValid@4 proc near ; CODE XREF: IopIsAddressRangeValid(x,x)+2Fp
.text:00439980 ; IopGetMaxValidMemorySize(x,x)+29p ...
.text:00439980
.text:00439980 var_8 = dword ptr -8
.text:00439980 var_4 = dword ptr -4
.text:00439980 VirtualAddress = dword ptr 8
.text:00439980
.text:00439980 mov edi, edi
.text:00439982 push ebp
.text:00439983 mov ebp, esp
.text:00439985 push ecx
.text:00439986 push ecx
.text:00439987 mov ecx, [ebp+VirtualAddress]
.text:0043998A push esi
.text:0043998B mov eax, ecx
.text:0043998D shr eax, 12h
.text:00439990 mov esi, 3FF8h
.text:00439995 and eax, esi
.text:00439997 sub eax, 3FA00000h
.text:0043999C mov edx, [eax]
.text:0043999E mov eax, [eax+4]
.text:004399A1 mov [ebp+var_4], eax
.text:004399A4 mov eax, edx
.text:004399A6 push edi
.text:004399A7 and eax, 1
.text:004399AA xor edi, edi
.text:004399AC or eax, edi
.text:004399AE jz short loc_439A11
.text:004399B0 mov edi, 80h
.text:004399B5 and edx, edi
.text:004399B7 push 0
.text:004399B9 mov [ebp+var_8], edx
.text:004399BC pop eax
.text:004399BD jz short loc_4399C3
.text:004399BF test eax, eax
.text:004399C1 jz short loc_439A15
.text:004399C3
.text:004399C3 loc_4399C3: ; CODE XREF: MmIsAddressValid(x)+3Dj
.text:004399C3 shr ecx, 9
.text:004399C6 and ecx, 7FFFF8h
.text:004399CC mov eax, [ecx-3FFFFFFCh]
.text:004399D2 sub ecx, 40000000h
.text:004399D8 mov edx, [ecx]
.text:004399DA mov [ebp+var_4], eax
.text:004399DD push ebx
.text:004399DE mov eax, edx
.text:004399E0 xor ebx, ebx
.text:004399E2 and eax, 1
.text:004399E5 or eax, ebx
.text:004399E7 pop ebx
.text:004399E8 jz short loc_439A11
.text:004399EA and edx, edi
.text:004399EC push 0
.text:004399EE mov [ebp+var_8], edx
.text:004399F1 pop eax
.text:004399F2 jz short loc_439A15
.text:004399F4 test eax, eax
.text:004399F6 jnz short loc_439A15
.text:004399F8 and ecx, esi
.text:004399FA mov ecx, [ecx-3FA00000h]
.text:00439A00 mov eax, 81h
.text:00439A05 and ecx, eax
.text:00439A07 xor edx, edx
.text:00439A09 cmp ecx, eax
.text:00439A0B jnz short loc_439A15
.text:00439A0D test edx, edx
.text:00439A0F jnz short loc_439A15
.text:00439A11
.text:00439A11 loc_439A11: ; CODE XREF: MmIsAddressValid(x)+2Ej
.text:00439A11 ; MmIsAddressValid(x)+68j
.text:00439A11 xor al, al
.text:00439A13 jmp short loc_439A17
.text:00439A15 ; ---------------------------------------------------------------------------
.text:00439A15
.text:00439A15 loc_439A15: ; CODE XREF: MmIsAddressValid(x)+41j
.text:00439A15 ; MmIsAddressValid(x)+72j ...
.text:00439A15 mov al, 1
.text:00439A17
.text:00439A17 loc_439A17: ; CODE XREF: MmIsAddressValid(x)+93j
.text:00439A17 pop edi
.text:00439A18 pop esi
.text:00439A19 leave
.text:00439A1A retn 4
.text:00439A1A _MmIsAddressValid@4 endp
分析后:
主要是判断PDE PTE的P,PS位。
---------------------------------------------------------------------------
.text:0043997A align 10h
.text:00439980 ; Exported entry 685. MmIsAddressValid
.text:00439980
.text:00439980 ; =============== S U B R O U T I N E =======================================
.text:00439980
.text:00439980 ; Attributes: bp-based frame
.text:00439980
.text:00439980 ; BOOLEAN __stdcall MmIsAddressValid(PVOID VirtualAddress)
.text:00439980 public _MmIsAddressValid@4
.text:00439980 _MmIsAddressValid@4 proc near ; CODE XREF: IopIsAddressRangeValid(x,x)+2Fp
.text:00439980 ; IopGetMaxValidMemorySize(x,x)+29p ...
.text:00439980
.text:00439980 var_8 = dword ptr -8
.text:00439980 var_4 = dword ptr -4
.text:00439980 VirtualAddress = dword ptr 8
.text:00439980
.text:00439980 mov edi, edi
.text:00439982 push ebp
.text:00439983 mov ebp, esp
.text:00439985 push ecx
.text:00439986 push ecx
.text:00439987 mov ecx, [ebp+VirtualAddress] ; ecx = VAddr
.text:0043998A push esi
.text:0043998B mov eax, ecx ; eax = VAddr
.text:0043998D shr eax, 12h ; VAddr >> 18
.text:00439990 mov esi, 3FF8h
.text:00439995 and eax, esi ; eax = PDPTI * 4KB + PDI * 8
.text:00439997 sub eax, 3FA00000h ; eax = C0600000 + PDPTI * 4KB + PDI * 8
.text:00439997 ; eax 指向了 PDE
.text:0043999C mov edx, [eax]
.text:0043999E mov eax, [eax+4] ; eax,edx = PDE
.text:004399A1 mov [ebp+var_4], eax
.text:004399A4 mov eax, edx ; eax = PDE低4字节
.text:004399A6 push edi
.text:004399A7 and eax, 1 ; 取PDE的P位
.text:004399AA xor edi, edi
.text:004399AC or eax, edi ; if (P==0) 返回假
.text:004399AE jz short loc_439A11
.text:004399B0 mov edi, 80h
.text:004399B5 and edx, edi ; 取PS位判断
.text:004399B7 push 0
.text:004399B9 mov [ebp+var_8], edx
.text:004399BC pop eax ; eax = 0
.text:004399BD jz short loc_4399C3 ; if (PS==0) 跳转到小页处理
.text:004399BF test eax, eax
.text:004399C1 jz short loc_439A15 ; 如果PS==1,即大页,就直接返回真
.text:004399C3
.text:004399C3 loc_4399C3: ; CODE XREF: MmIsAddressValid(x)+3Dj
.text:004399C3 shr ecx, 9 ; VAddr >> 9 效果相当于右移12位,然后乘以8
.text:004399C6 and ecx, 7FFFF8h ; ecx = PDPTI * 2MB + PDI * 4KB + PTI * 8
.text:004399CC mov eax, [ecx-3FFFFFFCh]
.text:004399D2 sub ecx, 40000000h ; ecx = C0000000 + PDPTI * 2MB + PDI * 4KB + PTI * 8
.text:004399D2 ; ecx 指向 PTE
.text:004399D8 mov edx, [ecx] ; edx = PTE低4字节
.text:004399DA mov [ebp+var_4], eax
.text:004399DD push ebx
.text:004399DE mov eax, edx ; eax = PTE低4字节
.text:004399E0 xor ebx, ebx ; ebx = 0
.text:004399E2 and eax, 1 ; 取PTE的P位
.text:004399E5 or eax, ebx
.text:004399E7 pop ebx
.text:004399E8 jz short loc_439A11 ; P==0 返回假
.text:004399EA and edx, edi ; PTE低4字节 & 80h,即取PAT位
.text:004399EC push 0
.text:004399EE mov [ebp+var_8], edx
.text:004399F1 pop eax
.text:004399F2 jz short loc_439A15 ; PAT==0 返回真
.text:004399F4 test eax, eax
.text:004399F6 jnz short loc_439A15
.text:004399F8 and ecx, esi ; 后面是判断PAT==1的情况,我就不分析了,看不懂
.text:004399FA mov ecx, [ecx-3FA00000h]
.text:00439A00 mov eax, 81h
.text:00439A05 and ecx, eax
.text:00439A07 xor edx, edx
.text:00439A09 cmp ecx, eax
.text:00439A0B jnz short loc_439A15
.text:00439A0D test edx, edx
.text:00439A0F jnz short loc_439A15
.text:00439A11
.text:00439A11 loc_439A11: ; CODE XREF: MmIsAddressValid(x)+2Ej
.text:00439A11 ; MmIsAddressValid(x)+68j
.text:00439A11 xor al, al
.text:00439A13 jmp short loc_439A17
.text:00439A15 ; ---------------------------------------------------------------------------
.text:00439A15
.text:00439A15 loc_439A15: ; CODE XREF: MmIsAddressValid(x)+41j
.text:00439A15 ; MmIsAddressValid(x)+72j ...
.text:00439A15 mov al, 1
.text:00439A17
.text:00439A17 loc_439A17: ; CODE XREF: MmIsAddressValid(x)+93j
.text:00439A17 pop edi
.text:00439A18 pop esi
.text:00439A19 leave
.text:00439A1A retn 4
.text:00439A1A _MmIsAddressValid@4 endp
八、编写代码实现修改页属性,实现应用层读写高2G内存地址
2-9-9-12
PDPTI-PDI-PTI-OFFSET 公式:
pPDE = 0xc0600000 + (PDPTI*4KB) + (PDI*8)
pPTE = 0xc0000000 + (PDPTI*2MB) + (PDI*4KB) + (PTI*8) 更高效的公式(MmIsAddressValid是这么干的)
pPDE = 0xc0600000 + ((addr >> 18) & 0x3ff8)
pPTE = 0xc0000000 + ((addr >> 9) & 0x7ffff8)
// ReadWriteH2G_2-9-9-12.cpp : Defines the entry point for the console application.
//#include "stdafx.h"
#include <windows.h>//2-9-9-12
//PDPTI-PDI-PTI-OFFSETDWORD *GetPDE(DWORD addr)
{//return (DWORD *)(0xc0600000 + ((addr >> 18) & 0x3ff8));DWORD PDPTI = addr >> 30;DWORD PDI = (addr >> 21) & 0x000001FF;DWORD PTI = (addr >> 12) & 0x000001FF;return (DWORD *)(0xC0600000 + PDPTI * 0x1000 + PDI * 8);
}DWORD *GetPTE(DWORD addr)
{//return (DWORD *)(0xc0000000 + ((addr >> 9) & 0x7ffff8));DWORD PDPTI = addr >> 30;DWORD PDI = (addr >> 21) & 0x000001FF;DWORD PTI = (addr >> 12) & 0x000001FF;return (DWORD *)(0xC0000000 + PDPTI * 0x200000 + PDI * 0x1000 + PTI * 8);
}void __declspec(naked) R0Function()
{__asm{push ebpmov ebp,espsub esp,0x1000pushadpushfd }__asm push fs//__asm int 3// 修改8003f048的U/S位*GetPDE(0x8003f048) |= 0x00000004;*GetPTE(0x8003f048) |= 0x00000004;// 修改PTE的G位*GetPTE(0x8003f048) &= 0xFFFFFEFF;//__asm int 3__asm pop fs__asm{popfdpopadadd esp,0x1000mov esp,ebppop ebpiretd}
}int _tmain(int argc, _TCHAR* argv[])
{printf("在IDT表构建中断门,请在windbg中执行下面的指令:\n");printf("eq 8003f500 %04xee00`0008%04x\n",(DWORD)R0Function>>16,(DWORD)R0Function & 0x0000FFFF);getchar();__asm int 0x20printf("0x8003f048 U/S,G位修改成功.\n");printf("*(PDWORD)0x8003f048 = %08x\n", *(PDWORD)0x8003f048); // 读*(PDWORD)0x8003f048 = 0x12345678; // 写printf("*(PDWORD)0x8003f048 = %08x\n", *(PDWORD)0x8003f048); // 读getchar();return 0;
}
九、测试XD位
我写了一个程序,是用一个指针指向一块内存,然后用汇编call过去。然后可以对比XD=0和XD=1时,CALL的结果。
// TestXD.cpp : Defines the entry point for the console application.
//#include "stdafx.h"
#include <Windows.h>char *buff;DWORD *GetPDE(DWORD addr)
{//return (DWORD *)(0xc0600000 + ((addr >> 18) & 0x3ff8));DWORD PDPTI = addr >> 30;DWORD PDI = (addr >> 21) & 0x000001FF;DWORD PTI = (addr >> 12) & 0x000001FF;return (DWORD *)(0xC0600000 + PDPTI * 0x1000 + PDI * 8);
}DWORD *GetPTE(DWORD addr)
{//return (DWORD *)(0xc0000000 + ((addr >> 9) & 0x7ffff8));DWORD PDPTI = addr >> 30;DWORD PDI = (addr >> 21) & 0x000001FF;DWORD PTI = (addr >> 12) & 0x000001FF;return (DWORD *)(0xC0000000 + PDPTI * 0x200000 + PDI * 0x1000 + PTI * 8);
}void __declspec(naked) R0Function()
{__asm{push ebpmov ebp,espsub esp,0x1000pushadpushfd }__asm push fs//__asm int 3// 修改buff的XD位*(GetPDE((DWORD)buff) + 1) |= 0x80000000;*(GetPTE((DWORD)buff) + 1) |= 0x80000000;//__asm int 3__asm pop fs__asm{popfdpopadadd esp,0x1000mov esp,ebppop ebpiretd}
}int _tmain(int argc, _TCHAR* argv[])
{// 申请一个内存页,写入硬编码 buff = (char *)VirtualAlloc(NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);printf("buff: %p\n", buff);BYTE bytecode [7] = {0x90,0xB8,0x01,0x00,0x00,0x00,0xC3}; // NOP, MOV EAX,1, RETmemcpy(buff,bytecode,7);// 测试,对比XD=0和XD=1的运行结果printf("输入XD位:");int xd;scanf("%d",&xd); // 输入0可以调用,输入1调用失败getchar();if (xd == 1){printf("在IDT表构建中断门,请在windbg中执行下面的指令:\n");printf("eq 8003f500 %04xee00`0008%04x\n",(DWORD)R0Function>>16,(DWORD)R0Function & 0x0000FFFF);getchar();__asm int 0x20printf("XD位修改成功,buff不可执行.\n");}DWORD dwEAX = 0;__asm{push eaxxor eax,eaxcall buffmov dwEAX,eaxpop eax};if (dwEAX == 0) printf("调用失败.\n");else if (dwEAX == 1) printf("调用成功.\n");printf("bye!\n");getchar();return 0;
}
如果XD=0,就是默认情况了,可以正常调用函数并返回。
如果将XD修改为1,那么执行CALL会失败,程序会卡死。
(25)2-9-9-12分页(下)相关推荐
- redis 系列25 哨兵Sentinel (高可用演示 下)
原文:redis 系列25 哨兵Sentinel (高可用演示 下) 一. Sentinel 高可用环境准备 1.1 Sentinel 集群环境 环境 说明 操作系统版本 CentOS 7.4.17 ...
- linux telnet localhost 25,telnet localhost 25 没反应. 大家帮忙看下什么问题...
telnet localhost 25 没反应. 大家帮忙看下什么问题... (2012-01-10 05:46:33) 标签: localhost 杂谈 telnet localhost 25 没反 ...
- Ubuntu 12.04 下编译Android 4.0.3
在Ubuntu 12.04 下编译了Android 4.0.3发现了一大堆错误,网上找了一堆的更改源码啊,Android.mk的解决方法,虽然可以编译成功,但都有点坑爹的成分,为了不误人子弟就分享出来 ...
- android studio3.12,Android Studio V3.12环境下TV开发教程(六)提供卡片视图
Android Studio V3.12环境下TV开发教程 文章源自:光谷佳武 https://blog.csdn.net/jiawuhan/article/details/80619656 在上一课 ...
- Ubuntu 12.04下安装Oracle Express 11gR2
Ubuntu 12.04下安装Oracle Express 11gR2 [我的笔记] 参考1:http://www.linuxidc.com/Linux/2012-09/71382.htm 参考2:h ...
- linux ubuntu 12.04 下默认是安装了openjdk的
ubuntu 12.04 下默认是安装了openjdk的,不过这个jdk问题比较多,因为你甚至无法启动Eclipse,所以还是需要自己安装jdk的. 1.下载jdk6 jdk6下载地址为:http:/ ...
- Ubuntu 12.04下搭建Web服务器 (MySQL+PHP+Apache)(转)
看了网上很多关于用linux操作系统搭建网站服务器的教程,于是我自己也测试了很多,但今天所测试的 Ubuntu 12.04下搭建Web网站服务器 (MySQL+PHP+Apache环境),感觉这个适合 ...
- 通过pyenv在Mac OS X 10.12.3下安装Python-3.6.0及“*** [install] Error 1”错误的解决方法
通过pyenv在Mac OS X 10.12.3下安装Python-3.6.0及"*** [install] Error 1"错误的解决方法 参考文章: (1)通过pyenv在Ma ...
- mysql webmail ubuntu12.04 imap_Ubuntu 12.04下搭建Web网站服务器 (MySQL+PHP+Apache环境)教程...
前言 看了网上很多关于用linux操作系统搭建网站服务器的教程,于是我自己也测试了很多,但今天所测试的 Ubuntu 12.04下搭建Web网站服务器 (MySQL+PHP+Apache环境),感觉这 ...
- edup无线网卡驱动安装linux,EDUP EP-N8513 (RTL8188CUS芯片)在Ubuntu 12.10下的wifi不能连接问题解决方法...
EDUP EP-N8513这款USB微型无线网卡在我刚装上的64位Ubuntu 12.10下虽然能被系统识别出来,但是并不能正常连接无线AP,具体表现为可以看到AP列表,尝试连接后不停的询问密码,即使 ...
最新文章
- 计算机系统的分类补充完整,数据库系统原(理B)13春A卷.doc
- PHP----------php封装的一些简单实用的方法汇总
- pandas使用replace函数将dataframe中None值以及其他异常编码值(例如,9999)替换为np.nan
- 智源成立面向可持续发展的人工智能智库并发布公益研究计划
- Qt配置GUI程序控制台输出
- idea加入springboot插件_带你搭一个SpringBoot+SpringData JPA的环境
- html5 手机拍视频滤镜,用canvas实现图片滤镜效果附演示_html5教程技巧
- php smarty 语法,php之Smarty根本语法和三大变量
- pandas遍历dataframe_chapter2-4 常用数据处理包Pandas整理4
- php聚合支付,pay: ThinkPHP开源聚合支付系统
- 在.net中使用javascript-Jint和Javascript .NET
- IMO Res MSC 307(88) 国际船舶材料防火试验
- matlab将水印图像嵌入图像,改进的图像自嵌入水印算法及其MATLAB实现
- 个性化茅台之中国酒韵·十大人物
- 一线技术人应该关注的四种思维能力
- Codeforces 985A. Chess Placing(1ni)(水题)(div.2)
- 《Java I/O》Chapter 1
- 政务服务一网通办建设方案(ppt)
- [图像]中值滤波(Matlab实现)
- JavaMail API 详解
热门文章
- mysql linux selected_MySQL的查询语句--SELECT
- Algorithm:机械优化设计的数学模型简介、常用优化方法、优化计算工具简介之详细攻略
- 成功解决This DCH driver package is not compatible with the currently installed version of Windows. This
- 成功解决No such file or directory: site-packages\\pyyaml-5.3-py3.6-win-amd64.egg\\EGG-INFO\\top_level.t
- TF之LSTM:基于Tensorflow框架采用PTB数据集建立LSTM网络的自然语言建模
- Py之gym:gym的简介、安装、使用方法之详细攻略
- Py之pyglet:Python之pyglet库的简介、安装、使用详细攻略
- Crawler:基于urllib库+实现爬虫有道翻译
- 统计学习方法第四章朴素贝叶斯法-李航
- Linux绝对路径和相对路径简单介绍