uint32_t edthreaded_fd::write(uint8_t * buffer, uint32_t size, int32_t response_size) { int32_t resp = 0; pthread_mutex_lock(&m_send_lock); if (size > m_write_buffer.size()) size = m_write_buffer.size(); for (uint32_t i = 0; i < size; ++i) { if (i == size-1) resp = response_size; m_write_buffer[m_write_curindex] = WriteVal(buffer[i], resp); ++m_write_curindex; if (m_write_curindex == m_write_rawindex) size = i; if (m_write_curindex == m_write_buffer.size()) m_write_curindex = 0; } pthread_mutex_unlock(&m_send_lock); return size; }
unsigned SegWriteConstExpr (FILE* F, ExprNode* E, int Signed, unsigned Size) /* Write a supposedly constant expression to the target file. Do a range ** check and return one of the SEG_EXPR_xxx codes. */ { static const unsigned long U_Hi[4] = { 0x000000FFUL, 0x0000FFFFUL, 0x00FFFFFFUL, 0xFFFFFFFFUL }; static const long S_Hi[4] = { 0x0000007FL, 0x00007FFFL, 0x007FFFFFL, 0x7FFFFFFFL }; static const long S_Lo[4] = { ~0x0000007FL, ~0x00007FFFL, ~0x007FFFFFL, ~0x7FFFFFFFL }; /* Get the expression value */ long Val = GetExprVal (E); /* Check the size */ CHECK (Size >= 1 && Size <= 4); /* Check for a range error */ if (Signed) { if (Val > S_Hi[Size-1] || Val < S_Lo[Size-1]) { /* Range error */ return SEG_EXPR_RANGE_ERROR; } } else { if (((unsigned long)Val) > U_Hi[Size-1]) { /* Range error */ return SEG_EXPR_RANGE_ERROR; } } /* Write the value to the file */ WriteVal (F, Val, Size); /* Success */ return SEG_EXPR_OK; }
//-------------------------------------------------------------------------------------- int _tmain(int argc, _TCHAR* argv[]) { m_hInstance = (HINSTANCE)GetModuleHandle(NULL); if (argc >= 3) { m_lpFontPath = argv[2]; m_lpFontName = argv[1]; printf(__FUNCTION__"(): Using external font %ws \"%ws\"\n", m_lpFontName, m_lpFontPath); } else { printf("USAGE: MsFontsFuzz.exe <font_name> <font_file> [options]\n"); goto end; } _stprintf_s(m_TmpFontPath, _T("__TMP__%s"), _tGetNameFromFullPath(m_lpFontPath)); DbgMsg(__FILE__, __LINE__, "[+] Temporary font file is \"%ws\"\n", m_TmpFontPath); if (_tcslen(m_TmpFontPath) >= 4) { _tcslwr(m_TmpFontPath + _tcslen(m_TmpFontPath) - 4); if (!_tcscmp(m_TmpFontPath + _tcslen(m_TmpFontPath) - 4, _T(".otf"))) { m_dwFontType = FONT_TYPE_OTF; DbgMsg(__FILE__, __LINE__, "[+] Font type is .OTF\n"); } else if (!_tcscmp(m_TmpFontPath + _tcslen(m_TmpFontPath) - 4, _T(".ttf"))) { m_dwFontType = FONT_TYPE_TTF; DbgMsg(__FILE__, __LINE__, "[+] Font type is .TTF\n"); } } RemoveFontResource(m_TmpFontPath); #ifdef USE_BOADCAST_MESSAGES SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0); #endif char ch = 0; memset(m_szTable, '.', sizeof(m_szTable) - 1); for (int i = 0; i < sizeof(m_szTable); i++) { if (i != 0 && i % 16 == 0) { m_szTable[i] = '\n'; continue; } if (ch >= 0x20) { m_szTable[i] = ch; } if (ch == 0x7f) { m_szTable[i] = 0; break; } ch += 1; } if (argc > 3) { // enumerate additional parameters for (int i = 3; i < argc; i++) { if (!_tcscmp(argv[i], _T("--test"))) { // single launch mode m_bTest = TRUE; } else if (!_tcscmp(argv[i], _T("--resume"))) { // resume fuzzing in the new process m_bResume = TRUE; } else if (!_tcscmp(argv[i], _T("--noisy"))) { // show lot of output information m_bNoisy = TRUE; } else if (!_tcscmp(argv[i], _T("--text")) && argc - i > 1) { #ifdef UNICODE // use caller-specified text for display WideCharToMultiByte( CP_ACP, 0, argv[i + 1], -1, m_szTable, sizeof(m_szTable) - 1, NULL, NULL ); #else strcpy_s(m_szTable, argv[i + 1]); #endif i++; } else if (!_tcscmp(argv[i], _T("--fix-crcs"))) { // fix incorrect checksums for the original font file m_bFixCrcs = TRUE; } else if (argc - i > 1 && argv[i][0] == '-') { /** * Process data generation options. */ LPCTSTR lpParam = argv[i] + 1; DWORD dwValue = 0; BOOL bFound = FALSE; if (!StrToIntEx(argv[i + 1], STIF_SUPPORT_HEX, (int *)&dwValue)) { DbgMsg(__FILE__, __LINE__, "[!] ERROR: Invalid value for parameter \"%ws\"\n", argv[i]); continue; } for (int i_n = 0; i_n < sizeof(m_Params) / sizeof(ENGINE_PARAM); i_n++) { // search parameter by name if (!_tcscmp(m_Params[i_n].lpName, lpParam)) { *(m_Params[i_n].pdwValue) = dwValue; bFound = TRUE; break; } } if (!bFound) { DbgMsg(__FILE__, __LINE__, "[!] ERROR: Unknown parameter \"%ws\"\n", argv[i]); } i++; } } } DbgInit(LOG_FILE_NAME); // check block size and range if (BLOCK_SIZE == 1) { if (BLOCK_RANGE_START >= 0xFF) { DbgMsg(__FILE__, __LINE__, __FUNCTION__"(): Invalid BLOCK_RANGE_START value (it must be <0xFF)\n"); goto end; } if (BLOCK_RANGE_END > 0xFF) { DbgMsg(__FILE__, __LINE__, __FUNCTION__"(): Invalid BLOCK_RANGE_END value (it must be <=0xFF)\n"); goto end; } } else if (BLOCK_SIZE == 2) { if (BLOCK_RANGE_START >= 0xFFFF) { DbgMsg(__FILE__, __LINE__, __FUNCTION__"(): Invalid BLOCK_RANGE_START value (it must be <0xFFFF)\n"); goto end; } if (BLOCK_RANGE_END > 0xFFFF) { DbgMsg(__FILE__, __LINE__, __FUNCTION__"(): Invalid BLOCK_RANGE_END value (it must be <=0xFFFF)\n"); goto end; } } else if (BLOCK_SIZE == 4) { if (BLOCK_RANGE_START >= 0xFFFFFFFF) { DbgMsg(__FILE__, __LINE__, __FUNCTION__"(): Invalid BLOCK_RANGE_START value (it must be <0xFFFFFFFF)\n"); goto end; } if (BLOCK_RANGE_END > 0xFFFFFFFF) { DbgMsg(__FILE__, __LINE__, __FUNCTION__"(): Invalid BLOCK_RANGE_END value (it must be <=0xFFFFFFFF)\n"); goto end; } } else { DbgMsg(__FILE__, __LINE__, __FUNCTION__"(): Invalid BLOCK_SIZE value (it must be 1, 2 or 4)\n"); goto end; } // check step size if (BLOCK_RANGE_N > BLOCK_RANGE_END) { DbgMsg(__FILE__, __LINE__, __FUNCTION__"(): Invalid BLOCK_RANGE_N value (it must be <=BLOCK_RANGE_END)\n"); goto end; } WNDCLASSEX wcex; ZeroMemory(&wcex, sizeof(wcex)); wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.hInstance = m_hInstance; wcex.lpszClassName = _T(WND_CLASS); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); m_hWndEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (m_hWndEvent == NULL) { DbgMsg(__FILE__, __LINE__, "CreateEvent() ERROR %d\n", GetLastError()); goto end; } // register window class if (RegisterClassEx(&wcex) == NULL) { DbgMsg(__FILE__, __LINE__, "RegisterClassEx() ERROR %d\n", GetLastError()); goto end; } // init random number generator init_genrand(GetTickCount()); SetUnhandledExceptionFilter(UnhandledExceptionError); // read input file if (ReadFromFile(m_lpFontPath, &m_pData, &m_dwDataSize)) { if (FILE_RANGE_START >= m_dwDataSize) { DbgMsg(__FILE__, __LINE__, __FUNCTION__"(): Invalid FILE_RANGE_START value (it must be <=FILE_SIZE)\n"); M_FREE(m_pData); return -1; } if (FILE_RANGE_END > m_dwDataSize) { DbgMsg(__FILE__, __LINE__, __FUNCTION__"(): Invalid FILE_RANGE_END value (it must be <FILE_SIZE)\n"); M_FREE(m_pData); return -1; } if (FILE_RANGE_END == 0) { FILE_RANGE_END = m_dwDataSize; } if (FILE_RANGE_START >= FILE_RANGE_END) { DbgMsg(__FILE__, __LINE__, __FUNCTION__"(): Invalid FILE_RANGE_START/FILE_RANGE_END values\n"); M_FREE(m_pData); return -1; } DbgMsg(__FILE__, __LINE__, "[+] %d bytes readed from \"%ws\"\n", m_dwDataSize, m_lpFontPath); if (!m_bResume && (m_dwFontType == FONT_TYPE_OTF || m_dwFontType == FONT_TYPE_TTF)) { OTF_TableByOffset(m_pData, (ULONG)-1); } if (m_bFixCrcs) { // write fixed checksums into the original file if (DumpToFile(m_lpFontPath, m_pData, m_dwDataSize)) { DbgMsg(__FILE__, __LINE__, "[+] Checksums has been fixed for font file \"%ws\"\n", m_lpFontPath); } } else if (m_bTest) { // single run with the unchanged font file if (DumpToFile(m_TmpFontPath, m_pData, m_dwDataSize)) { FuzzIteration(); } } else { DbgMsg(__FILE__, __LINE__, "[+] Fuzzing params:\n\n"); // print parameters values for (int i_n = 0; i_n < sizeof(m_Params) / sizeof(ENGINE_PARAM); i_n++) { DbgMsg(__FILE__, __LINE__, " %20ws = 0x%.8x\n", m_Params[i_n].lpName, *(m_Params[i_n].pdwValue)); } DbgMsg(__FILE__, __LINE__, "\n"); DbgMsg(__FILE__, __LINE__, "[+] Processing cases...\n\n"); // align buffer size by block size m_dwAlignedDataSize = XALIGN_UP(m_dwDataSize, BLOCK_SIZE); // allocate output buffer if (m_pAlignedData = M_ALLOC(m_dwAlignedDataSize)) { char *lpszBigBuff = (char *)M_ALLOC(BIG_BUFFER_LENGTH); if (lpszBigBuff) { FillMemory(lpszBigBuff, BIG_BUFFER_LENGTH, 'A'); } PVOID pBigData = M_ALLOC(m_dwDataSize + BIG_BUFFER_LENGTH); // for each byte/word/dword of input file... for (DWORD i = FILE_RANGE_START; i < FILE_RANGE_END; i += BLOCK_SIZE) { DbgMsg(__FILE__, __LINE__, "Offset=0x%.8x TotalSize=0x%.8x File=%.8x\n", i, m_dwDataSize, m_dwCasesProcessed); POTF_TABLE_HEADER Table = NULL; if (m_dwFontType == FONT_TYPE_OTF || m_dwFontType == FONT_TYPE_TTF) { Table = OTF_TableByOffset(m_pData, i); if (Table == NULL) { // skip OTF/TTF data outside the tables continue; } } if (BLOCK_RANGE_N > 0) { // fuze each value with the step size == BLOCK_RANGE_N for (DWORD n = XALIGN_DOWN(BLOCK_RANGE_START, BLOCK_RANGE_N); n < XALIGN_DOWN(BLOCK_RANGE_END, BLOCK_RANGE_N); n += BLOCK_RANGE_N) { // write plain value WriteVal(i, BLOCK_SIZE, n, n, n); if (BLOCK_SIZE > 1) { // write randomized value WriteVal(i, BLOCK_SIZE, n, n + getrand(0, BLOCK_RANGE_N - 1), n + getrand(0, BLOCK_RANGE_N - 1) ); } } } // zero-bytes stuff WriteVal(i, BLOCK_SIZE, 0x00, 0x0000, 0x00000000); // integer overflow stuff WriteVal(i, BLOCK_SIZE, 0xFF, 0xFFFF, 0xFFFFFFFF); // invalid user-mode pointers WriteVal(i, BLOCK_SIZE, 0x0D, 0x0D0D, 0x0D0D0D0D); if (lpszBigBuff && pBigData) { /** * Write big ASCI data after the each byte. */ memcpy(pBigData, m_pData, i); memcpy((PUCHAR)pBigData + i, lpszBigBuff, BIG_BUFFER_LENGTH); memcpy((PUCHAR)pBigData + i + BIG_BUFFER_LENGTH, (PUCHAR)m_pData + i, m_dwDataSize - i); if (m_dwFontType == FONT_TYPE_OTF || m_dwFontType == FONT_TYPE_TTF) { POTF_FILE_HEADER Hdr = (POTF_FILE_HEADER)pBigData; POTF_TABLE_HEADER Table = (POTF_TABLE_HEADER)((PUCHAR)pBigData + sizeof(OTF_FILE_HEADER)); POTF_TABLE_HEADER CurrentTable = NULL; for (USHORT t = 0; t < htons(Hdr->numTables); t++) { ULONG Offset = htonl(Table->offset), Length = htonl(Table->length); if (i >= Offset && i < Offset + Length) { // fix OTF/TTF table checksum and length ULONG Sum = OTF_CalcTableChecksum((ULONG *)((PUCHAR)pBigData + Offset), Length); Table->checkSum = htonl(Sum); Table->length = htonl(Length); CurrentTable = Table; break; } Table += 1; } if (CurrentTable) { Table = (POTF_TABLE_HEADER)((PUCHAR)pBigData + sizeof(OTF_FILE_HEADER)); for (USHORT t = 0; t < htons(Hdr->numTables); t++) { ULONG Offset = htonl(Table->offset), Length = htonl(Table->length); if (Offset > htonl(CurrentTable->offset)) { // fix offsets of the other tables Table->offset = htonl(Offset + BIG_BUFFER_LENGTH); } Table += 1; } } } if (DumpToFile(m_TmpFontPath, pBigData, m_dwDataSize + BIG_BUFFER_LENGTH)) { FuzzIteration(); m_dwCasesProcessed++; } } if (m_dwCasesProcessed > MAX_CASES_PER_PROCESS) { TCHAR szSelf[MAX_PATH], szCmdLine[MAX_PATH]; GetModuleFileName(GetModuleHandle(NULL), szSelf, MAX_PATH); _stprintf_s( szCmdLine, MAX_PATH, _T("\"%s\" \"%s\" \"%s\" -BLOCK_SIZE 0x%x -BLOCK_RANGE_START 0x%x -BLOCK_RANGE_END 0x%x -BLOCK_RANGE_N 0x%x -FILE_RANGE_START 0x%x --resume Y"), szSelf, m_lpFontName, m_lpFontPath, BLOCK_SIZE, BLOCK_RANGE_START, BLOCK_RANGE_END, BLOCK_RANGE_N, i ); if (m_bNoisy) { _tcscat(szCmdLine, _T(" --noisy Y")); } STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(pi)); ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); // create a new fuzzer instance if (!CreateProcess(NULL, szCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { MessageBox(0, _T("CreateProcess() fails"), _T("ERROR"), MB_ICONERROR); } ExitProcess(0); } } DbgMsg(__FILE__, __LINE__, "Done; %d cases processed\n", m_dwCasesProcessed); if (pBigData) { M_FREE(pBigData); } if (lpszBigBuff) { M_FREE(lpszBigBuff); } M_FREE(m_pAlignedData); } } M_FREE(m_pData); } else { DbgMsg(__FILE__, __LINE__, __FUNCTION__"(): Error while reading input file\n"); } end: if (m_hWndEvent) { CloseHandle(m_hWndEvent); } printf("Press any key to quit...\n"); _getch(); return 0; }