├── .gitignore ├── README.md ├── license.txt ├── strings.ncb ├── strings.sln ├── strings.suo ├── strings ├── ReadMe.txt ├── basics.cpp ├── basics.h ├── binary2strings.cpp ├── binary2strings.hpp ├── dirent.h ├── extracted_string.cpp ├── extracted_string.hpp ├── json.hpp ├── memory_strings.cpp ├── memory_strings.h ├── module.cpp ├── module.h ├── print_buffer.cpp ├── print_buffer.h ├── resource.h ├── stdafx.cpp ├── stdafx.h ├── string_model.h ├── string_parser.cpp ├── string_parser.h ├── strings.cpp ├── strings.rc ├── strings.vcproj ├── strings.vcproj.glmcdona-PC.glmcdona.user ├── strings.vcxproj ├── strings.vcxproj.filters └── targetver.h └── x64 ├── Debug ├── strings.exe ├── strings.ilk └── strings.pdb └── Release ├── strings - Copy (2).exe ├── strings - Copy.exe ├── strings.exe ├── strings.pdb └── test └── asdf.bin /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | 11 | [Dd]ebug*/ 12 | [Rr]elease/ 13 | 14 | build/ 15 | lib/ 16 | .vs/ 17 | 18 | [Tt]est[Rr]esult 19 | [Bb]uild[Ll]og.* 20 | 21 | *_i.c 22 | *_p.c 23 | *.ilk 24 | *.meta 25 | *.obj 26 | *.pch 27 | *.pdb 28 | *.pgc 29 | *.pgd 30 | *.rsp 31 | *.sbr 32 | *.tlb 33 | *.tli 34 | *.tlh 35 | *.tmp 36 | *.vspscc 37 | *.vssscc 38 | .builds 39 | 40 | *.pidb 41 | 42 | *.log 43 | *.scc 44 | # Visual C++ cache files 45 | ipch/ 46 | *.aps 47 | *.ncb 48 | *.opensdf 49 | *.sdf 50 | 51 | # Visual Studio profiler 52 | *.psess 53 | *.vsp 54 | 55 | # Guidance Automation Toolkit 56 | *.gpState 57 | 58 | # ReSharper is a .NET coding add-in 59 | _ReSharper*/ 60 | 61 | *.[Rr]e[Ss]harper 62 | 63 | # NCrunch 64 | *.ncrunch* 65 | .*crunch*.local.xml 66 | 67 | # Installshield output folder 68 | [Ee]xpress 69 | 70 | # DocProject is a documentation generator add-in 71 | DocProject/buildhelp/ 72 | DocProject/Help/*.HxT 73 | DocProject/Help/*.HxC 74 | DocProject/Help/*.hhc 75 | DocProject/Help/*.hhk 76 | DocProject/Help/*.hhp 77 | DocProject/Help/Html2 78 | DocProject/Help/html 79 | 80 | # Click-Once directory 81 | publish 82 | 83 | # Publish Web Output 84 | *.Publish.xml 85 | 86 | # Others 87 | [Bb]in 88 | [Oo]bj 89 | sql 90 | TestResults 91 | [Tt]est[Rr]esult* 92 | *.Cache 93 | ClientBin 94 | [Ss]tyle[Cc]op.* 95 | ~$* 96 | *.dbmdl 97 | 98 | *.[Pp]ublish.xml 99 | 100 | Generated_Code #added for RIA/Silverlight projects 101 | 102 | # Backup & report files from converting an old project file to a newer 103 | # Visual Studio version. Backup files are not needed, because we have git ;-) 104 | _UpgradeReport_Files/ 105 | Backup*/ 106 | UpgradeLog*.XML 107 | 108 | # NuGet 109 | packages/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # strings2 - Extract strings from binary files and process memory 2 | Strings2 is a Windows command-line tool for extracting strings from binary data. On top of the classic Sysinternals strings approach, this tool includes: 3 | * Multi-lingual string extraction, such as Russian, Chinese, etc. 4 | * Machine learning model filters out junk erroneous string extractions to reduce noise. 5 | * String extractions from process memory. 6 | * Recursive and wildcard filename matching. 7 | * Json output option for automation integration. (Also see python module version [binary2strings](https://github.com/glmcdona/binary2strings)) 8 | 9 | I also recommend looking at [FLOSS](https://github.com/mandiant/flare-floss) from Mandiant a cross-platform string extraction solver with a different set of features. 10 | 11 | ## Installation 12 | Download the [latest release binary](https://github.com/glmcdona/strings2/releases). 13 | 14 | ## Example Usage 15 | 16 | Dump all strings from `malware.exe` to stdout: 17 | 18 | * ```strings2 malware.exe``` 19 | 20 | Dump all strings from all `.exe` files in the `files` folder to the file `strings.txt`: 21 | * ```strings2 ./files/*.exe > strings.txt``` 22 | 23 | Dump strings from a specific process id, including logging the module name and memory addresses of each match: 24 | * ```strings2 -f -s -pid 0x1a3 > process_strings.txt``` 25 | 26 | Extract strings from `malware.exe` to a json file: 27 | * ```strings2 malware.exe -json > strings.json``` 28 | 29 | ## Documentation 30 | 31 | ```strings.exe (options) file_pattern``` 32 | 33 | * `file_pattern` can be a folder or file. Wildcards (`*`) are supported in the filename parts - eg `.\files\*.exe`. 34 | 35 | |Option|Description| 36 | |--|--| 37 | |-r|Recursively process subdirectories.| 38 | |-f|Prints the filename/processname for each string.| 39 | |-F|Prints the full path and filename for each string.| 40 | |-s|Prints the file offset or memory address span of each string.| 41 | |-t|Prints the string type for each string. UTF8, or WIDE_STRING.| 42 | |-wide|Prints only WIDE_STRING strings that are encoded as two bytes per character.| 43 | |-utf|Prints only UTF8 encoded strings.| 44 | |-a|Prints both interesting and not interesting strings. Default only prints interesting non-junk strings.| 45 | |-ni|Prints only not interesting strings. Default only prints interesting non-junk strings.| 46 | |-e|Escape new line characters.| 47 | |-l [num_chars]|Minimum number of characters that is a valid string. Default is 4.| 48 | |-b [start]\(:[end]\)|Scan only the specified byte range for strings. Optionally specify an end offset as well.| 49 | |-pid [pid]|The strings from the process address space for the specified PID will be dumped. Use a '0x' prefix to specify a hex PID.| 50 | |-system|Dumps strings from all accessible processes on the system. This takes awhile.| 51 | |-json|Writes output as json. Many flags are ignored in this mode.| 52 | 53 | 54 | ## Version History 55 | 56 | Version 2.0 (May 29, 2022) 57 | - Complete overhaul of the tool. 58 | - Upgrade string extraction engine from [binary2strings](https://github.com/glmcdona/binary2strings). 59 | - Add support for multilingual strings. 60 | - Added ML model to filter junk erroneous string extractions. 61 | - Add option to dump only a specified offset range. 62 | - Add json output option. 63 | - Add memory address and module name logging. 64 | - Fixes to 64bit process string dumping. 65 | 66 | Version 1.2 (Apr 21, 2013) 67 | - Added "-a" and "-u" flags to extract only ascii or unicode strings. 68 | - Fixed a bug when processing certain filenames. 69 | 70 | Version 1.1 (Nov 22, 2012) 71 | - Added "-r" recursive flag option. 72 | - Added "-pid" and "-system" flag options to specify process input sources. 73 | - Piped input data is now supported. 74 | - Various fixes. 75 | 76 | Version 1.0 (Sept 20, 2012) 77 | - Initial release. -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Geoff McDonald 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 7 | * Neither the name split-code nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 8 | 9 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 10 | -------------------------------------------------------------------------------- /strings.ncb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glmcdona/strings2/38630f3b058d48043d426adf80a3e1fcd715ad7c/strings.ncb -------------------------------------------------------------------------------- /strings.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.32428.217 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "strings", "strings\strings.vcxproj", "{12872240-F930-4859-8FE1-16ED68B57411}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Debug|x64 = Debug|x64 12 | Release|Win32 = Release|Win32 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {12872240-F930-4859-8FE1-16ED68B57411}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {12872240-F930-4859-8FE1-16ED68B57411}.Debug|Win32.Build.0 = Debug|Win32 18 | {12872240-F930-4859-8FE1-16ED68B57411}.Debug|x64.ActiveCfg = Debug|x64 19 | {12872240-F930-4859-8FE1-16ED68B57411}.Debug|x64.Build.0 = Debug|x64 20 | {12872240-F930-4859-8FE1-16ED68B57411}.Release|Win32.ActiveCfg = Release|Win32 21 | {12872240-F930-4859-8FE1-16ED68B57411}.Release|Win32.Build.0 = Release|Win32 22 | {12872240-F930-4859-8FE1-16ED68B57411}.Release|x64.ActiveCfg = Release|x64 23 | {12872240-F930-4859-8FE1-16ED68B57411}.Release|x64.Build.0 = Release|x64 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {CB55428F-0116-4975-9331-DE0979C2844F} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /strings.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glmcdona/strings2/38630f3b058d48043d426adf80a3e1fcd715ad7c/strings.suo -------------------------------------------------------------------------------- /strings/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | CONSOLE APPLICATION : strings Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this strings application for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your strings application. 9 | 10 | 11 | strings.vcproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | strings.cpp 18 | This is the main application source file. 19 | 20 | ///////////////////////////////////////////////////////////////////////////// 21 | Other standard files: 22 | 23 | StdAfx.h, StdAfx.cpp 24 | These files are used to build a precompiled header (PCH) file 25 | named strings.pch and a precompiled types file named StdAfx.obj. 26 | 27 | ///////////////////////////////////////////////////////////////////////////// 28 | Other notes: 29 | 30 | AppWizard uses "TODO:" comments to indicate parts of the source code you 31 | should add to or customize. 32 | 33 | ///////////////////////////////////////////////////////////////////////////// 34 | -------------------------------------------------------------------------------- /strings/basics.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "basics.h" 3 | 4 | void PrintLastError(LPTSTR lpszFunction) 5 | { 6 | // Retrieve the system error message for the last-error code 7 | LPVOID lpMsgBuf; 8 | LPVOID lpDisplayBuf; 9 | DWORD dw = GetLastError(); 10 | 11 | FormatMessage( 12 | FORMAT_MESSAGE_ALLOCATE_BUFFER | 13 | FORMAT_MESSAGE_FROM_SYSTEM | 14 | FORMAT_MESSAGE_IGNORE_INSERTS, 15 | NULL, 16 | dw, 17 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 18 | (LPTSTR) &lpMsgBuf, 19 | 0, NULL ); 20 | 21 | // Display the error message and exit the process 22 | lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, 23 | (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR)); 24 | StringCchPrintf((LPTSTR)lpDisplayBuf, 25 | LocalSize(lpDisplayBuf) / sizeof(TCHAR), 26 | TEXT("%s failed with error %d: %s"), 27 | lpszFunction, dw, lpMsgBuf); 28 | 29 | fwprintf(stderr,(LPCTSTR) lpDisplayBuf ); 30 | 31 | LocalFree(lpMsgBuf); 32 | LocalFree(lpDisplayBuf); 33 | } -------------------------------------------------------------------------------- /strings/basics.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | void PrintLastError(LPTSTR lpszFunction); -------------------------------------------------------------------------------- /strings/binary2strings.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "binary2strings.hpp" 3 | 4 | using namespace std; 5 | 6 | size_t try_utf8_char_step(const unsigned char* buffer, size_t buffer_size, long offset) 7 | { 8 | // Returns 0 if it's not likely a valid utf8 character. For ascii range of characters it requires 9 | // the character to be a displayable character. 10 | if (buffer_size < offset + 1) 11 | return 0; 12 | 13 | unsigned char first_byte = buffer[offset]; 14 | 15 | if (first_byte < 0x80) 16 | { 17 | if (is_displayable_ascii[first_byte]) 18 | return 1; 19 | return 0; 20 | } 21 | 22 | if (first_byte < 0xC2) 23 | return 0; // Ignore continuation bytes, they are non displayable. 24 | 25 | if (first_byte > 0xF4) 26 | return 0; // Invalid bytes for Utf8, https://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences 27 | 28 | if (first_byte < 0xE0) 29 | { 30 | // 2 byte encoding 31 | if (buffer_size < offset + 2) 32 | return 0; 33 | 34 | if ((buffer[offset + 1] & 0xC0) != 0x80) 35 | return 0; 36 | 37 | // Now convert the character to wchar_t 38 | wchar_t c = 0; 39 | c |= (first_byte & 0x1F) << 6; 40 | c |= (buffer[offset + 1] & 0x3F); 41 | 42 | // Require the character to be seen at least once in commoncrawl web scape 43 | if (is_seen_commoncrawl.find(c) == is_seen_commoncrawl.end()) 44 | return 0; // Invalid unicode character 45 | 46 | return 2; 47 | } 48 | 49 | if (first_byte < 0xF0) 50 | { 51 | // 3 byte encoding 52 | if (buffer_size < offset + 3) 53 | return 0; 54 | 55 | if ((buffer[offset + 1] & 0xC0) != 0x80) 56 | return 0; 57 | 58 | if ((buffer[offset + 2] & 0xC0) != 0x80) 59 | return 0; 60 | 61 | // Now convert the character to wchar_t 62 | wchar_t c = 0; 63 | c |= (first_byte & 0x0F) << 12; 64 | c |= (buffer[offset + 1] & 0x3F) << 6; 65 | c |= (buffer[offset + 2] & 0x3F); 66 | 67 | // Check special cases 68 | if (first_byte == 0xE0) 69 | { 70 | // Check for overlong case 71 | if (c < 0x800) 72 | return 0; // Overlong 73 | } 74 | else if (first_byte == 0xED) 75 | { 76 | // Check for surrogate pair case 77 | if (c >= 0xD800 && c <= 0xDFFF) 78 | return 0; 79 | } 80 | 81 | // Require the character to be seen at least once in commoncrawl web scape 82 | if (is_seen_commoncrawl.find(c) == is_seen_commoncrawl.end()) 83 | return 0; // Invalid unicode character 84 | 85 | return 3; 86 | } 87 | 88 | // 4 byte encoding is out of scope, since it is outside the Basic Multilingual Plane. 89 | 90 | return 0; 91 | } 92 | 93 | int get_language_group(wchar_t c) 94 | { 95 | // Returns the language group of a unicode wchar. 96 | // Return value of 0x0 denotes an invalid language group, and 0x1 denotes Latin. 97 | return bmp_12bits_to_group[c >> 4]; // Leading 12 bits identify the language group 98 | } 99 | 100 | // Note: Buffer overrun security checks disabled, since they added ~50% overhead. 101 | __declspec(safebuffers) extracted_string* try_extract_string(const unsigned char* buffer, size_t buffer_size, long offset, size_t min_chars) 102 | { 103 | // Try extracting the string as either utf8 or unicode wchar format. Returns None if it's not a valid string. 104 | int i; 105 | int char_count; 106 | 107 | // Try to parse as utf8 first 108 | size_t utf_char_len; 109 | utf_char_len = try_utf8_char_step(buffer, buffer_size, offset); 110 | 111 | if (utf_char_len >= 0) 112 | { 113 | i = offset; 114 | char_count = 0; 115 | while (i < buffer_size && utf_char_len > 0) 116 | { 117 | i += utf_char_len; 118 | char_count++; 119 | 120 | // Try parse next character 121 | utf_char_len = try_utf8_char_step(buffer, buffer_size, i); 122 | } 123 | 124 | if (char_count >= min_chars) 125 | { 126 | // Return the extracted string 127 | return new extracted_string((char*)(buffer + offset), i - offset, TYPE_UTF8, offset, i - 1); 128 | } 129 | 130 | // Not a valid utf8 string, try a unicode string parse still 131 | } 132 | 133 | // Try extract as unicode wchar 134 | // Unicode logic requires all characters to be in the same BMP block or in the BMP Basic Latin 135 | // Block. (eg any single BMP block plus latin in the same string is OK) 136 | 137 | // The non-basic-latin language group identified 138 | int group = -1; 139 | i = offset; 140 | char_count = 0; 141 | 142 | // Parse as unicode 143 | while (i + 1 < buffer_size) 144 | { 145 | wchar_t c = *(wchar_t*)(buffer + i); 146 | 147 | if (c == 0) 148 | break; 149 | 150 | if (c < 0x100) 151 | { 152 | // Basic Latin, require it to be displayable ascii if in this range 153 | if (!is_displayable_ascii[c]) 154 | break; 155 | } 156 | else 157 | { 158 | // Non-basic Latin 159 | 160 | // Require the character to be seen at least once in commoncrawl web scape 161 | if (is_seen_commoncrawl.find(c) == is_seen_commoncrawl.end()) 162 | break; // Invalid unicode character 163 | 164 | // Require it to be in the same character language group of what's already identified 165 | int group_new = get_language_group(c); 166 | 167 | if (group_new == 0) 168 | break; // Invalid language group 169 | 170 | // Check if it's the same language group as the previous characters 171 | if (group == -1) 172 | group = group_new; 173 | else if (group_new != group) 174 | break; // Invalid language transition 175 | } 176 | 177 | i += 2; 178 | char_count++; 179 | } 180 | 181 | if (char_count >= min_chars) 182 | { 183 | // Return the extracted string 184 | return new extracted_string((wchar_t*)(buffer + offset), i - offset, TYPE_WIDE_STRING, offset, i - 2); 185 | } 186 | 187 | return NULL; // Invalid string at this offset 188 | } 189 | 190 | 191 | std::tuple, bool> try_extract_string_tuple(const unsigned char* buffer, size_t buffer_size, long offset, size_t min_chars, bool only_interesting) 192 | { 193 | // Simple wrapper to return a tuple instead 194 | extracted_string* s = try_extract_string(buffer, buffer_size, offset, min_chars); 195 | if (s != NULL) 196 | { 197 | bool is_interesting = s->is_interesting(); 198 | 199 | if (!only_interesting || is_interesting) 200 | { 201 | // Create a tuple to return 202 | auto result = std::make_tuple( 203 | s->get_string(), 204 | s->get_type_string(), 205 | std::pair(s->get_offset_start(), s->get_offset_end()), 206 | is_interesting 207 | ); 208 | 209 | delete s; 210 | 211 | return result; 212 | } 213 | } 214 | 215 | return std::make_tuple("", "", std::make_pair(0, 0), false); 216 | } 217 | 218 | 219 | vector, bool>> extract_all_strings(const unsigned char buffer[], size_t buffer_size, size_t min_chars, bool only_interesting) 220 | { 221 | // Process the specified binary buffer and extract all strings 222 | long offset = 0; 223 | vector, bool>> r_vect; 224 | vector proba_interesting_vect; 225 | vector proba_interesting_avg_vect; 226 | extracted_string* s; 227 | 228 | float last_proba_interestings[WINDOW_SIZE] = { 0.0f }; 229 | 230 | while (offset + min_chars <= buffer_size) 231 | { 232 | // Process this offset 233 | s = try_extract_string((unsigned char*)buffer, buffer_size, offset, min_chars); 234 | 235 | if (s) 236 | { 237 | float proba_interesting = s->get_proba_interesting(); 238 | 239 | // Add the new string 240 | r_vect.push_back( 241 | tuple, bool>( 242 | s->get_string(), 243 | s->get_type_string(), 244 | std::pair(s->get_offset_start(), s->get_offset_end()), 245 | proba_interesting > 0.5 246 | ) 247 | ); 248 | 249 | // Update the last proba_interesting array 250 | float total = 0.0; 251 | 252 | // Shift the moving window of interesting strings 253 | for (int j = WINDOW_SIZE - 2; j >= 0; j--) 254 | { 255 | total += last_proba_interestings[j]; 256 | last_proba_interestings[j + 1] = last_proba_interestings[j]; 257 | } 258 | 259 | // Add the new interesting string value 260 | last_proba_interestings[0] = proba_interesting; 261 | total += proba_interesting; 262 | float average = total / (float)WINDOW_SIZE; 263 | proba_interesting_avg_vect.push_back(average); 264 | proba_interesting_vect.push_back(proba_interesting); 265 | 266 | // Advance by the byte-length of the string 267 | offset += (long)s->get_size_in_bytes(); 268 | 269 | // Cleanup 270 | delete s; 271 | } 272 | else { 273 | // Advance the offset by 1 274 | offset += 1; 275 | } 276 | } 277 | 278 | // Have a pass through the strings averaging the interestingness and filtering 279 | vector, bool>> r_vect_filt; 280 | for (int i = 0; i < r_vect.size(); i++) 281 | { 282 | // Get the interestingness 283 | float proba_interesting_avg = 0.0; 284 | 285 | // This string is interesting is the window just before or after is interesting 286 | proba_interesting_avg = proba_interesting_avg_vect[i]; 287 | 288 | if (i + WINDOW_SIZE < proba_interesting_avg_vect.size()) 289 | { 290 | if (proba_interesting_avg_vect[i + WINDOW_SIZE] > proba_interesting_avg) 291 | proba_interesting_avg = proba_interesting_avg_vect[i + WINDOW_SIZE]; 292 | } 293 | 294 | if (!only_interesting || proba_interesting_avg >= 0.2 || proba_interesting_vect[i] >= 0.5) 295 | { 296 | r_vect_filt.push_back( 297 | tuple, bool>( 298 | std::get<0>(r_vect[i]), 299 | std::get<1>(r_vect[i]), 300 | std::get<2>(r_vect[i]), 301 | proba_interesting_avg >= 0.15 || proba_interesting_vect[i] >= 0.5 302 | ) 303 | ); 304 | } 305 | } 306 | 307 | return r_vect_filt; 308 | } 309 | -------------------------------------------------------------------------------- /strings/binary2strings.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "extracted_string.hpp" 6 | #include 7 | 8 | using namespace std; 9 | 10 | #define WINDOW_SIZE 11 11 | 12 | // Quick way of checking if a character value is displayable ascii 13 | static bool is_displayable_ascii[0x100] = 14 | /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 15 | /* 0x00 */ {false,false,false,false, false,false,false,false, false,true ,true ,false, false,true ,false,false, 16 | /* 0x10 */ false,false,false,false, false,false,false,false, false,false,false,false, false,false,false,false, 17 | /* 0x20 */ true ,true ,true ,true , true ,true ,true ,true , true ,true ,true ,true , true ,true ,true ,true , 18 | /* 0x30 */ true ,true ,true ,true , true ,true ,true ,true , true ,true ,true ,true , true ,true ,true ,true , 19 | /* 0x40 */ true ,true ,true ,true , true ,true ,true ,true , true ,true ,true ,true , true ,true ,true ,true , 20 | /* 0x50 */ true ,true ,true ,true , true ,true ,true ,true , true ,true ,true ,true , true ,true ,true ,true , 21 | /* 0x60 */ true ,true ,true ,true , true ,true ,true ,true , true ,true ,true ,true , true ,true ,true ,true , 22 | /* 0x70 */ true ,true ,true ,true , true ,true ,true ,true , true ,true ,true ,true , true ,true ,true ,false, 23 | /* 0x80 */ false,false,false,false, false,false,false,false, false,false,false,false, false,false,false,false, 24 | /* 0x90 */ false,false,false,false, false,false,false,false, false,false,false,false, false,false,false,false, 25 | /* 0xA0 */ false,false,false,false, false,false,false,false, false,false,false,false, false,false,false,false, 26 | /* 0xB0 */ false,false,false,false, false,false,false,false, false,false,false,false, false,false,false,false, 27 | /* 0xC0 */ false,false,false,false, false,false,false,false, false,false,false,false, false,false,false,false, 28 | /* 0xD0 */ false,false,false,false, false,false,false,false, false,false,false,false, false,false,false,false, 29 | /* 0xE0 */ false,false,false,false, false,false,false,false, false,false,false,false, false,false,false,false, 30 | /* 0xF0 */ false,false,false,false, false,false,false,false, false,false,false,false, false,false,false,false}; 31 | 32 | // Maps the first 12 bits of a unicode character to the language group in Unicode BMP Plane0. Zero denotes not a valid language. See python code below. 33 | // See ./../Tools/unicode_language_groups.py for the python code that generated this table. 34 | static char bmp_12bits_to_group[0xFFF] = { 35 | 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, 36 | 6,6,6,6,6,6,6,6,6,6,2,2,2,2,2,2,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,2,2,2,2,2,2,2,2,9,9,9,9,9,9,9,9,6,6,6,6,6,6,6,6,4,4,4,4,4,4,4,4,4,4,4,8,8,8,8,8,4,4,4,4,4,6,6,6,6,6,6,6,6,6,6,6,9,9,6,6,6,6,6,6,6,6,6,2,2,2,2,2,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,4,4,4,4,4,4,4,4,2,2,2,2,9,4,4,4,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 37 | 2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,1,1,2,2,2,2,2,2,2,2,2,2,2,5,5,5,5,5,5,5,5,5,5,5,2,2,0,0,0,0,0,0,0,0,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,0,12, 38 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,12,12,12,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, 39 | 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,0,0,0,0,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, 40 | 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, 41 | 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, 42 | 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, 43 | 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, 44 | 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, 45 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,2,2,2,2,2,2,5,5,5,5,5,5,7,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,4,4,0,4,4,4,4,4,4,4,4,4,4,4,4,6,6,6,9,9,9,7,7,9,9,9,9,9,9,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,4,4,5,5,5,1,1,1,1,8,8,8,8,8,4,4,4,4,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 46 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 47 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 48 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 49 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 50 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,1,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,7,2,7,7,7,7,3,3,3,3,3,3,3,3,3,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 51 | }; 52 | 53 | // List of common UNICODE characters seen at least once in CommonCrawl 54 | // https://stackoverflow.com/questions/22184624/unicode-character-usage-statistics 55 | // https://docs.google.com/spreadsheet/ccc?key=0AjHWiIkH6KdCdDd1TnppTnZub1k2MTNhV05xdk5yUXc&usp=sharing 56 | // Note exclude 0xfeff byte order marker. 57 | static std::unordered_set is_seen_commoncrawl({ 58 | 0x20,0x65,0x61,0x69,0x6f,0x74,0x6e,0x72,0x73,0xa,0x6c,0x64,0x63,0x75,0x68,0x6d,0xfffd,0x67,0x70,0x66,0x79,0x62,0x2e,0x30,0xa0,0x53,0x76,0x77,0x31,0x41,0x6b,0x32,0x2c,0x2d,0x43,0x54,0x45,0x4d,0x50,0x49,0x52,0x44,0x4c,0x42,0x33,0x4e,0x29,0x28,0x35,0x46,0x3a,0x4f,0x48,0x34,0x47,0x39,0x7a,0x57,0x78,0x56,0x36,0x2f,0x55,0x38,0xd,0x37,0x6a,0x4b,0x27,0x7c,0x4a,0xe9,0x71,0x59,0x30fc,0x306e,0x26,0x22,0x43e,0x430,0x438,0x435,0x3d,0x21,0x442,0x3e,0x3f,0x43d,0x51,0x30f3,0x5a,0x3044,0x441,0x30b9,0x306b,0x5b,0x30c8,0x5d,0x58,0x440,0x5f,0x24,0x3092,0x3002,0xfc,0x3059,0x308b,0x627,0x3001,0x3066,0x2a,0x30a4,0xe4,0x3057,0x43b,0x43a,0x306f,0x3b,0x432,0xa3,0x3067,0x25,0xf3,0x2b,0x307e,0xe1,0x305f,0x3068,0xf6,0x306a,0x304c,0x30c3,0x644,0x30af,0x30fb,0x30ea,0x43c,0x54c1,0x30e9,0x30eb,0x30a2,0x43f,0xe0,0x434,0x3000,0xed,0x30bf,0x304a,0x23,0x2019,0x30ab,0x3064,0x3053,0x308a,0x304b,0x30ec,0x645,0x44f,0x443,0x44c,0x64a,0x65e5,0x44b,0x30d3,0x3c,0x30d5,0x3089,0xbb,0x648,0x3063,0x3082,0x30b0,0x5d9,0x30b3,0x431,0x20ac,0x3046,0x304f,0x308c,0xa9,0x3055,0x631,0x5186,0x30de,0x30e5,0x5546,0x30d7,0x30e1,0xe8,0x30b7,0xff1a,0x7d,0x2013,0x7b,0x437,0x433,0x2022,0x6708,0x5e74,0x439,0x3060,0x30c6,0x672c,0x30c9,0x3093,0x62a,0x3042,0x661f,0x639,0x646,0x5d5,0x3061,0x131,0x25ba,0x30b5,0x898b,0x30b8,0x304d,0x4eba,0xe7,0x30d0,0x30e0,0x30a3,0x420,0x30c1,0x30ed,0x300c,0x300d,0x6599,0x6587,0x30df,0x40,0x628,0x4e2d,0x5de,0xf1,0x5e8,0x421,0xfa,0x65b0,0x7684,0x447,0xff09,0x7528,0xff08,0x4e00,0x3088,0x62f,0x446,0xf4,0x30ad,0x4f1a,0x307f,0x103,0x3051,0x203a,0x5c,0x5927,0x305b,0x629,0x30aa,0x5dc,0xff01,0x8005,0x633,0x15f,0x95,0x201c,0x4f5c,0xffe5,0x3054,0x5408,0x3081,0x5831,0xe5,0x647,0x2026,0x6700,0x10d,0xea,0x30a8,0x201d,0x60c5,0xb7,0x9001,0x142,0x30d6,0x445,0x5d1,0xdf,0x30a6,0x884c,0x308f,0x3079,0x30cb,0x5d4,0x41f,0x51fa,0x4e07,0x3048,0x5206,0x4ef6,0x643,0x5185,0x305d,0x641,0x30ba,0x5ea,0x642,0x436,0x3b1,0x7121,0x30c7,0x30bd,0x3084,0x30e7,0x41a,0xee,0x30da,0x4e0a,0x5165,0x5834,0x30bb,0x2014,0x3069,0x6642,0x6210,0x691c,0x30e3,0x65b9,0x30c0,0x30ca,0x412,0x30d9,0x30dd,0x66f8,0x5728,0x95a2,0x901a,0x5d0,0x41e,0x30c4,0x7d22,0x683c,0x7e,0x7269,0x444,0xe2,0x30d1,0x30d4,0x81ea,0x448,0x5eab,0xff0c,0x4ee5,0x5e97,0x56fd,0x30db,0x4fa1,0x44e,0x5dd,0xff5e,0x3b9,0x767b,0x33a1,0x6ce8,0x62c,0x8cb7,0x9593,0x80fd,0x6295,0xff06,0x5ba2,0x6c17,0xff1f,0x91d1,0x30ae,0x697d,0x5e9,0x62d,0x30a7,0x914d,0x5bb6,0xc774,0x5b50,0x4e0b,0x5e0,0x9,0x6a2a,0x3010,0x634,0x8a73,0x3011,0x3078,0x3b5,0x3bf,0x9332,0x69d8,0x5b9a,0x30ef,0x17e,0x6d5c,0xab,0x30ac,0x624b,0x119,0x5e2,0x5e6,0x653e,0x7d04,0x11f,0x521d,0x751f,0x5b66,0x793e,0x3bd,0x5c0f,0x5730,0x524d,0x8981,0x98f2,0x6570,0x30a1,0x161,0x53d6,0x30e6,0x5e4,0xdc,0x636,0x4f53,0x984c,0x308d,0xb0,0x30cd,0xe3,0x410,0x7a3f,0x7d30,0x3058,0x41d,0x449,0x767a,0x4ed8,0x6709,0x5d7,0x30b4,0x54e1,0x30b1,0x30b2,0x753b,0x7406,0x637,0x90e8,0x8457,0x15b,0x500b,0x640,0x5229,0x96c6,0x9023,0x635,0x301c,0x30dc,0x5168,0x7248,0x30d8,0x17c,0x5e,0x4fbf,0x591a,0x96fb,0x4ea4,0x60,0x5e1,0x540d,0x65c5,0x163,0x4e8b,0x7279,0x63a2,0x98df,0x4e0d,0x8003,0x53f0,0xb2e4,0xff11,0x8fbc,0xff5c,0x8ca9,0x5d3,0x8868,0xc3,0xb294,0x571f,0x97f3,0x25a0,0x5ba4,0xae,0x611f,0x8a18,0x5d2,0x53c2,0x5f97,0x89a7,0x6211,0x5177,0x8a9e,0x793a,0x52a0,0x4fe1,0x52d5,0x8aad,0x99c5,0x4ed6,0x63db,0x5c4b,0x529b,0x4f4d,0x418,0x305a,0x623,0x53ef,0x7d9a,0x3c4,0x58f2,0x304e,0x6027,0x5f53,0x66f4,0x5e38,0x5fc3,0x8a00,0x41c,0x898f,0x6728,0x9ad8,0x25cf,0x5df,0x649,0x516c,0x5929,0x7f51,0xff10,0x5668,0x601d,0x8fd4,0x4e86,0x6301,0x6cd5,0x3bc,0x130,0x53e3,0x753a,0x6771,0x5bb9,0x76ee,0xd6,0x422,0x548c,0x30e2,0x4f7f,0x3c3,0x92,0x307b,0x771f,0x30e4,0x5de5,0x3bb,0x6025,0x105,0x5ea6,0x5e02,0x5e7,0x554f,0x3080,0x3c1,0x5b89,0x610f,0x3c5,0xc5d0,0x5bfe,0x623f,0x958b,0x5973,0x30a9,0x5f8c,0x414,0x8c46,0x3083,0x2018,0x7acb,0x107,0xd7,0xd55c,0x6559,0x62e,0x7c73,0x7f8e,0x5db,0x4eca,0x5f0f,0x53e4,0x2192,0xc4,0x5916,0x7530,0x4ee3,0x44d,0xc758,0x76f8,0x5b9f,0x9762,0x5225,0x5fc5,0x3070,0xb85c,0x671f,0x8f09,0x660e,0x6a5f,0x662f,0x70b9,0x50cf,0xc9,0x4e88,0x9053,0x411,0x4e16,0x670d,0xc2a4,0x5199,0x3073,0xff12,0x30cf,0x6307,0x597d,0x9a13,0x6b69,0x30ce,0x4ecb,0x82b1,0x8ffd,0x72b6,0xae30,0x3b3,0x144,0x540c,0x5ddd,0x696d,0x417,0x7236,0x6240,0x535a,0x578b,0x897f,0xc9c0,0x6c34,0x5c45,0x8cc3,0xd558,0x2122,0x7a0e,0x5d8,0x3076,0x9650,0xc744,0x41b,0x30b6,0x7b49,0x6b21,0x266a,0x151,0x969b,0x77e5,0x451,0x53d7,0xc2dc,0xac00,0x8eca,0x6f14,0x7d39,0xc790,0x5149,0x80,0x78ba,0x203b,0x13e,0x2605,0x5473,0x544a,0x9152,0x5316,0x25bc,0xda,0x5d6,0x9078,0x4f1d,0x6d3b,0x8cb8,0x80b2,0xb2,0x8a08,0x5f92,0x5f79,0x5909,0x6cc1,0xc544,0xb4,0x8aac,0xc740,0x5c4a,0x6765,0xc1,0x7b2c,0x73fe,0x8fd1,0xc7,0x623b,0x2514,0x539f,0x6d77,0x5c71,0xbf,0xace0,0x66f2,0x56de,0x165,0x3b7,0x4e3b,0x5358,0x4fdd,0x5317,0x5468,0x89c6,0xc5b4,0x4f55,0x201e,0x8a71,0xc0ac,0x7523,0x8272,0xfb,0x89e3,0x756a,0x5bb4,0x8cbb,0x305e,0x30d2,0x306d,0x4eac,0x713c,0x8c61,0x3005,0x5cf6,0x8ac7,0x826f,0xc11c,0x60f3,0x6761,0x6b4c,0x25aa,0x3ba,0xf5,0x53f7,0x754c,0x7ba1,0x2606,0xb9ac,0x5357,0x6b63,0x8cfc,0xb300,0x5e2d,0x5230,0x91ce,0x8a2d,0xb5,0x5207,0x9580,0x413,0x3087,0x428,0x679c,0x63b2,0x9891,0x91cf,0xe32,0x9577,0x671b,0x4ea7,0xd3,0x7d50,0x7dda,0xa1,0x5148,0xc778,0x5411,0x632,0x90fd,0x6d0b,0x4f60,0x5c11,0xb77c,0x7a7a,0x7d61,0x3c2,0x6e80,0xb3c4,0xf9,0x63a,0xff13,0x3052,0xb97c,0x455,0x88fd,0x3af,0x3072,0x5e73,0xd654,0x706b,0x8a8d,0x5143,0x795e,0x5f71,0x630,0x6982,0x6f2b,0x201a,0xc77c,0x2039,0x5173,0x424,0x7535,0x63d0,0x300e,0x89b3,0x5178,0x300f,0x9664,0xff62,0xad6d,0xff63,0x7403,0x770b,0x622,0x59cb,0x6620,0x55b6,0x91cd,0x79c1,0x52e2,0x3056,0xfd,0x30f4,0xbcf4,0x4e50,0x592a,0x52a8,0x3050,0x4f9b,0x5f62,0x8a55,0x85,0x39c,0xb2c8,0x8fba,0xb4dc,0x985e,0x4ed5,0x4e8c,0x62a5,0x6cc,0x98a8,0x3ad,0x5c02,0x5e0c,0xd2b8,0x5238,0x88c5,0x141,0x415,0x4e09,0x16d,0x3a1,0x767d,0x7a2e,0xb098,0x4e2a,0x7b54,0x7533,0x8eab,0x6c42,0x7d4c,0x5f15,0x63a8,0xc218,0x6d41,0xb9cc,0x3c0,0x30f6,0x7cfb,0xd574,0x85e4,0x5b57,0x5bcc,0x5171,0x53cb,0x621,0xac8c,0x9032,0x7fcc,0x93,0x5efa,0x5065,0x7f6e,0xc788,0xff15,0x7fa9,0x7968,0xba,0x7ecf,0x64ad,0x8074,0x9774,0xd1,0x8cea,0x9054,0x975e,0xeb,0x6238,0x5fdc,0x8f7d,0x2500,0x7d42,0x57ce,0x5ca1,0x9752,0x5f37,0x4e1a,0x423,0x7740,0x53ce,0x8b1d,0x90ce,0xc804,0x11d,0x56f3,0x606f,0xe23,0x96,0xff0f,0x8054,0x251c,0x63a1,0xb8cc,0x7ae0,0x629e,0x770c,0x65ad,0x5ea7,0x672a,0x6b74,0x3ac,0x6bd4,0xc81c,0x5b58,0xc601,0x82f1,0x62b,0x118,0x8bc1,0x968e,0x3071,0x673a,0x625,0x79d1,0x57fa,0x641c,0x663e,0x76f4,0x3b2,0xc5,0xc694,0x8907,0x7d20,0x85cf,0xc815,0x6d17,0x8bc4,0xa5,0xc0c1,0x2190,0x7247,0x56fe,0x8db3,0x3ae,0x4ef7,0xff14,0x42f,0x7de8,0x904b,0x5236,0x6750,0x456,0x6caa,0x7c7b,0xff21,0x405,0x627f,0x8336,0x9875,0x72ec,0x9069,0x821e,0x53f8,0x518d,0x6237,0x5e2f,0xc73c,0x5e83,0x89d2,0x65e9,0x795d,0xc7a5,0x3c9,0x6226,0x8bba,0x798f,0x6280,0x533b,0x767e,0x53cd,0x5b8c,0x4f20,0x9244,0xb9c8,0x5982,0x403,0x3086,0x3b6,0x7ad9,0xb4e4,0x591c,0xbd80,0x5404,0x7a0b,0x4e0e,0x4e4b,0xc6b0,0xe19,0x52a9,0x2665,0x7b11,0x3ce,0x611b,0x666f,0x6577,0x3a3,0x7136,0xadf8,0x7edc,0x9996,0x457,0x300a,0x79fb,0x42d,0x4e8e,0x9055,0x7e41,0x2212,0x8d44,0x66dc,0x3cc,0x4f0a,0xff18,0xe17,0x8996,0x300b,0x5e7f,0x8089,0x171,0x8cc7,0xc5ec,0xbbf8,0x6536,0x542b,0xff4d,0x53d1,0x25c6,0x5ff5,0x8bb0,0x44a,0x83ef,0x8ad6,0x901f,0xacfc,0x6574,0x5eb7,0xff24,0xd0,0x626,0x6821,0x6b8b,0x84,0x685c,0xbb34,0x96d1,0xb3d9,0x6bb5,0x4f4e,0x8bf7,0xc131,0x521b,0x5341,0xe48,0xe07,0x63a5,0x8449,0x394,0xac10,0x7537,0xc2e0,0x6e29,0xcd,0x39d,0xc18c,0x391,0xc624,0x585a,0x6b64,0x9020,0x58eb,0x4f4f,0x30bc,0x70ed,0x53f2,0x4f01,0x8d77,0x8abf,0xc6d0,0x5948,0x7d44,0x2502,0x6539,0x7531,0x65bd,0x8a3c,0x69cb,0x4e3e,0x8679,0x8bb8,0x8bcd,0x6e08,0x6c38,0xc6b4,0x307c,0xc8fc,0x638,0x58f0,0xff0b,0x160,0x8d85,0x4e03,0xb178,0x5e78,0x9662,0x653f,0x982d,0x98ce,0xc720,0x9ebb,0x5e33,0xe40,0x305c,0x77f3,0x5bf9,0xe01,0x666e,0x8857,0x6c11,0x6b62,0xff19,0x4efb,0x4e3a,0xbe44,0x6d88,0x427,0x7565,0xbaa8,0x10c,0x5347,0x592b,0x6848,0x8ee2,0x3c6,0x520a,0x109,0x65e0,0x95ee,0x5df1,0x8fc7,0xe22,0x6ca2,0xc2,0x7cbe,0x805e,0x6df1,0x529f,0xd130,0x8853,0x101,0x5d0e,0x7c4d,0x9806,0x904e,0x67e,0xc640,0x5217,0x5f69,0xa7,0xe2d,0x6751,0x7522,0x8425,0x15e,0x559c,0x6253,0x5305,0x9500,0x7518,0x9031,0x738b,0x60a8,0x8def,0x8acb,0xd588,0x534a,0x9928,0x518c,0x5272,0x8cde,0xad6c,0x6398,0x9858,0x30e8,0x6781,0x3075,0x60c,0x6797,0x402,0x5bfa,0x679a,0x67e5,0x53bb,0x5f85,0x590f,0x4e57,0x9b54,0x406,0x6b66,0x7814,0x5fae,0xd0c0,0x9999,0x8b58,0xbc15,0x95e8,0x80e1,0x7389,0x8c37,0x5f55,0x52d9,0x6a21,0x82e5,0x5f7c,0x5011,0x7b80,0xc5f0,0xc791,0x395,0x3b4,0x4e21,0x9ad4,0x8377,0x8f6c,0x62e1,0x82b8,0x671d,0x5c55,0x7d0d,0xf2,0x81f4,0x65cf,0x5e2e,0x5145,0xff05,0x675f,0x6625,0x5da,0x7ea7,0x52a1,0x8bae,0xc9c4,0x8a8c,0xc801,0x7dcf,0x96e2,0xad,0xe21,0xacf3,0x5409,0x843d,0x9ec4,0x7bc9,0xba74,0x6cbb,0x516b,0x643a,0x6e38,0xff16,0xac1c,0xce58,0x6e2f,0x491,0x6703,0x2032,0x5fd8,0xff30,0x65f6,0x91cc,0x5bae,0xacf5,0x94,0x5275,0x57df,0xff0e,0x6ce2,0x5e03,0xc784,0x7981,0x8bfb,0x6c7a,0xc704,0xe41,0x4e45,0xb7ec,0xc138,0x2021,0x5bc6,0x604b,0x652f,0x6fc0,0xb808,0x4f86,0x573a,0x4e5f,0x458,0xe35,0x606d,0xef,0x533a,0x5712,0x5355,0x677f,0x522b,0x454,0x15a,0x4eec,0x8056,0x822c,0x7bc0,0x2193,0x7dd2,0x76e4,0x4f8b,0x5c06,0xff23,0x6e05,0x7b56,0x8535,0x6975,0xc6a9,0x7d99,0x4fc2,0x6255,0xac83,0x6749,0x5dfb,0x4e95,0x677e,0x5fa9,0x5099,0xad00,0x63cf,0x4e28,0x514b,0x6af,0x5802,0x3a0,0x7a4d,0xc990,0x5df4,0x8bbe,0x5e9c,0x95f4,0x61f,0x5947,0x8001,0xce,0x6613,0x3c7,0x5b9d,0x73b0,0x6271,0x7570,0x7d19,0xd504,0x80f8,0x547d,0xff1e,0x5370,0x5dde,0x7a76,0x899a,0x60aa,0x8208,0x7387,0x7ffb,0x672b,0x4e94,0x53ca,0xb9ce,0x7167,0x88cf,0x9898,0xff17,0x8fbe,0x96e3,0x8c6a,0x6839,0xcd9c,0x8c4a,0x5e3,0xbc14,0x6c5f,0x8a0e,0x9605,0x540e,0xba54,0xc911,0x8a33,0x565,0xe31,0x3008,0x3009,0x5e8a,0xff34,0x5287,0x5c31,0x8f38,0x5024,0x5de6,0xc124,0x7ebf,0x3cd,0x5708,0x72c2,0x7fa4,0xff43,0x4e1c,0xc120,0x52dd,0x5267,0x8fce,0x5bbf,0x9ea6,0x4fee,0xff57,0xe44,0x4e08,0x99ac,0xc870,0xb1,0x6885,0x5361,0xb370,0xd560,0x5fb7,0xc57c,0x8a66,0x5176,0x65af,0x40a,0x97d3,0x9b5a,0x4e18,0x25cb,0x7559,0x4e13,0x5339,0x5bf8,0x8349,0x6575,0x4f3c,0xa4,0xc0dd, 59 | 0x620f,0x8ca0,0x8b1b,0x8b70,0x65bc,0x17a,0x672d,0xbc1c,0x827a,0xcd94,0xd1a0,0x425,0xd0a4,0x4f11,0x5b85,0x30be,0x3065,0x9632,0xcd5c,0x793c,0x8102,0x4e26,0x5f20,0x83dc,0xd68c,0x9019,0x89c8,0x9808,0x7231,0x9802,0xd30c,0x5922,0x594f,0x984d,0x5f00,0x5b63,0xc2b5,0x67fb,0x76db,0x4e92,0xbcf8,0x614b,0x547c,0x539a,0x97ff,0x5e2b,0x70ba,0xff3d,0x6697,0xb144,0x111,0xe49,0x5426,0x4e48,0x5747,0x5c1a,0xff3b,0x8077,0x159,0xc2e4,0xe04,0x641e,0x8fd9,0x8ba4,0x5531,0xb0b4,0x5f35,0x6cca,0x800c,0xff33,0x7bb1,0x7b1b,0x56db,0x56e3,0x6b73,0x98ef,0x512a,0x7aef,0x79f0,0x8fdb,0x68b1,0x5dee,0x8baf,0xce74,0x5f01,0x56e0,0x173,0xcc9c,0x523a,0x5bff,0x9ed2,0x957f,0x5343,0x6ca1,0x9045,0x6483,0x7d1a,0x7b97,0x6d4b,0x5883,0x6743,0x89aa,0x3041,0x5a31,0xba85,0xff2f,0x7d71,0x5f88,0x516d,0x5373,0x104,0xd604,0x3b8,0xff2c,0x5907,0x7d00,0x8a95,0xff22,0x5fa1,0x90a3,0xd53c,0x4e89,0x5c5e,0x6bce,0xac04,0x4e7e,0x773c,0x7d76,0xb514,0x64e,0x5e45,0xc785,0x5c40,0x5e94,0xacbd,0x62c5,0x8f6f,0x501f,0x7801,0xff4f,0x767c,0x7efc,0x5feb,0x15d,0x71b1,0x5ca9,0x96c4,0x6b7b,0x7384,0xd06c,0xc560,0x5224,0x57fc,0x6d4f,0x6216,0x8efd,0x786e,0x88ab,0x8bed,0x5931,0x53f3,0x75c5,0xd488,0x79cb,0x153,0x529e,0x8f03,0xb418,0x4e9b,0x135,0x76ca,0x8cac,0x9bae,0x5b9e,0xacc4,0xe2a,0x73a9,0xbc84,0x79d8,0x934b,0xff2b,0x8b66,0x514d,0x259,0x4ed9,0x52df,0xff65,0x663c,0x914e,0xb4f1,0x534e,0x7fd4,0x5e55,0xbc29,0xb9d0,0x6069,0x5c3e,0x6b32,0x8282,0x4ef2,0x5e30,0x6863,0x66ff,0x8217,0x904a,0xc7ac,0x6c41,0x63a7,0x8350,0x864e,0xba70,0xff1c,0x7c21,0x96a0,0xb798,0xac15,0x592e,0xbb3c,0x5e72,0x5354,0x505c,0x5b97,0x6e96,0x6218,0x7ed3,0x964d,0xd3ec,0x8a3a,0xc158,0x7834,0xd788,0x5bc4,0xff2a,0xa2,0xc5ed,0x4e01,0x8fb2,0xb9e4,0x117,0xd638,0x9988,0x6f1,0x9014,0x95dc,0x2020,0x6674,0xbb38,0x629c,0x8bd1,0x6545,0xbc88,0x306c,0x8d34,0xff32,0x674e,0x6d74,0x70ad,0xc5c8,0x5897,0x5348,0x6bba,0x5e26,0x9805,0xb41c,0xad50,0x7bc7,0xbc18,0x6a4b,0x68ee,0x9a6c,0x8f66,0x8bf4,0x9009,0xe6,0x3074,0x8feb,0x7fd2,0x8f91,0x5915,0xe1e,0xc5c5,0xff49,0x8239,0xcf54,0x5019,0xff2d,0x4f46,0x5e95,0x40f,0x536b,0xb2f9,0x672f,0x8d8a,0xbd84,0x839e,0x6d3e,0x12b,0xe30,0x732b,0x8d22,0x5170,0x7686,0x4f0e,0xe15,0x61c9,0xff2e,0x2028,0x5f25,0x6696,0x6392,0x5150,0x5df2,0xac01,0xc6d4,0xec,0x99a8,0x5e08,0x8d64,0xc74c,0x6e90,0x5727,0x5074,0x89c2,0x6e7e,0x6d66,0x534f,0x96e8,0x64b,0x202a,0x963f,0x6807,0x552e,0x2116,0x5e5,0x6f0,0xd1b5,0x416,0x6c7d,0x8ba9,0x5fd7,0x518a,0x8fdd,0x77ed,0xb824,0x716e,0xe27,0x8ca8,0xccb4,0xff36,0x8840,0x5f1f,0xbc30,0xe02,0x426,0xd5,0x71e5,0x102,0x74b0,0x5427,0xc0,0xa8,0x39f,0x6298,0xe08,0x56f2,0x56ed,0xff1b,0x453,0x6bdb,0xc18d,0xd310,0x4e70,0x6c0f,0x7a81,0x878d,0x301,0x624d,0xb974,0x7642,0xbc95,0xbcfc,0xc548,0x5c3d,0x7f57,0x8bd5,0x7159,0x8be5,0xff40,0x76e3,0x6bcf,0x590d,0x72af,0x7f8a,0x9b45,0x6cb9,0x9732,0xad8c,0x6f6e,0x7d75,0x52b9,0x52e4,0x75db,0x99d0,0x81f3,0x8ab0,0x5904,0xb3,0x76df,0xc6b8,0xff45,0x53ea,0x62db,0x6b53,0x8bdd,0xff25,0xe1a,0xb9c9,0x51b7,0x9a70,0xd589,0x5934,0x2191,0x6162,0x5438,0x8ddd,0xa6,0x6bcd,0x9589,0x4e38,0x4ec0,0x725b,0x708a,0x8846,0x5965,0xff41,0xff28,0x564c,0x8a2a,0xe20,0x393,0x4f50,0x5957,0x653b,0x6cb3,0x7b14,0xb9,0xc608,0x6837,0xc988,0x85ac,0x7fbd,0x822a,0x724c,0x8d39,0xb2e8,0x4f48,0x63f4,0x17b,0x8d2d,0xcc28,0x51fb,0xb09c,0x94d,0x83d3,0xff1d,0x7edf,0xd2f0,0x5e79,0x8fd8,0x5f8b,0x6001,0xac70,0x7948,0xb140,0xae08,0x21d2,0x4ffa,0xb450,0x7591,0xff53,0x9801,0x7f6a,0xb9e8,0xe42,0xe29,0x5b87,0x6a9,0x2200,0x6c49,0x5a92,0x6628,0x8c03,0x632f,0x53c8,0x7ec8,0x5417,0x9854,0xbe0c,0x25b6,0xe14,0xe25,0x9060,0x6770,0x5b98,0x65ec,0x9700,0x5a03,0xbaa9,0x8e8d,0x30fd,0xae00,0x6075,0x6557,0x82e6,0x5999,0x6563,0x3077,0x62e9,0x6fef,0x9280,0x9d8f,0x54f2,0x419,0xc9c1,0x7e54,0x51ac,0x53cc,0x7d14,0x3ca,0x8b77,0x50cd,0x59ff,0xb358,0xd50c,0x62cd,0xc800,0x5a5a,0x78ef,0x683d,0x6b22,0xb2a5,0x57f9,0x5bdd,0x699c,0x5bb3,0x51c6,0x79c0,0xf8,0x5175,0x7dd1,0x9759,0x73ed,0x94fa,0x820e,0x6e1b,0x8133,0x4eab,0x113,0x5ead,0x8d70,0xe34,0x6d44,0x5e76,0x6df7,0xc54a,0x6cbf,0x907a,0x570b,0x9a5a,0x98db,0x20aa,0x89c1,0x99,0x542c,0xb354,0xc5f4,0x7701,0xbd,0x25b2,0x6551,0x8af8,0x8ca1,0xae4c,0x66ae,0xff26,0x42c,0x4e73,0x62bc,0x745e,0x786c,0x8bda,0x6790,0x650,0x7ec6,0x6614,0xc6cc,0x39b,0x5ba1,0xc5c6,0xd45c,0xc288,0x1ebf,0x6f9,0x30a5,0x603b,0x525b,0x5e93,0x64ae,0x7ae5,0x888b,0x8edf,0x108,0x8a5e,0xb124,0x3085,0x5f3e,0x8896,0xb2ec,0x796d,0xce5c,0x88d5,0x9769,0x662d,0xb6,0x221e,0x5cb8,0x7db1,0x90f5,0x8ff7,0x9aa8,0x1ec7,0x8de1,0x5f80,0x7b7e,0x9ed1,0x89bd,0x73cd,0x6e58,0x79cd,0x836f,0xd0dc,0x4f26,0x91e3,0x9645,0x500d,0x52b4,0x5f31,0x8f93,0x98de,0x57cb,0xce90,0x62c9,0x6a19,0xc0b0,0x25ce,0x6311,0xb0a8,0xd3b8,0x6f5c,0x967a,0x3014,0xd6c4,0xd8,0x6c88,0x5247,0x3015,0x6843,0xcee4,0xc644,0x6388,0x7d66,0x9707,0x6e21,0x928,0x50b7,0x6f22,0xbcf5,0x4e9a,0x676f,0x6a39,0x6cc9,0xe43,0x554a,0x63ee,0x4f59,0xff31,0x52e7,0x4e5d,0x5c04,0x63da,0x967d,0x8f2a,0xb0a0,0x8655,0x8bbf,0xd398,0x88dc,0x6e2c,0x9f8d,0x5c0e,0x9686,0x93f,0x56fa,0x5e7c,0xff0d,0xb85d,0xadf9,0x53b3,0x80cc,0x7206,0x9ce5,0x968f,0x8587,0xc678,0x983c,0xcc98,0x3a6,0x8cc0,0xc21c,0x5098,0x711a,0x5352,0x5b88,0xd559,0x939,0x61b6,0x969c,0xe37,0xc885,0xc9d1,0x59d4,0xd14c,0x8bfa,0x7259,0x9000,0xc2dd,0x4f18,0x667a,0xb9ad,0x9084,0x50d5,0x8863,0xd22c,0xff29,0x5742,0x6c14,0x5237,0x6c96,0xc591,0xb3c5,0x940,0x5c07,0x8cb4,0x106,0xac74,0x9648,0xe16,0x524a,0x7d05,0x8a70,0x9803,0x59d3,0x7d5e,0x10e,0x697c,0x6d4e,0x7ea2,0x5cf0,0x81ed,0x6d25,0xb54c,0xff3e,0x59b9,0x5012,0x5584,0x72ac,0x7763,0xb791,0xbbfc,0x8ecd,0x60d1,0xb7f0,0x561,0x4f0f,0x8594,0x9ed8,0x682a,0x5a66,0xe2b,0xb9b0,0xc900,0x80aa,0x4e91,0x6b27,0xb825,0xcd08,0xac19,0xbbf,0x6e6f,0x638c,0x540,0x8fd0,0x575,0x652,0xbcd,0x6b65,0x392,0x576,0xc62c,0x580,0x6d32,0x17d,0x6b3e,0xff39,0x10f,0x6afb,0x96c5,0x8033,0x4ed4,0xac,0x62ec,0x6a29,0xaca9,0x5a18,0x6ce3,0xbb4,0x7f16,0x95b2,0xc810,0x16b,0xba4,0x9db4,0xc2ec,0xbae,0xacb0,0xff58,0x926,0x7af9,0x5553,0x79d2,0xc99d,0x5bfc,0x8179,0x6bbb,0x7b46,0x885b,0x9006,0x505a,0x9451,0x6669,0x7dca,0xd37c,0x7597,0xb204,0x900f,0x5979,0x639b,0x6717,0x96a3,0x7a97,0x8ff0,0xff4e,0x56c,0x9e97,0x76ae,0x8d23,0x578,0x5b09,0x582,0x885d,0x978b,0x7af6,0x52c9,0x7ed9,0x523b,0x5c64,0x566,0x7eb3,0x8131,0x96f0,0x266b,0xb8e8,0x6f2,0xe38,0x6dfb,0x8ae6,0x9003,0x714e,0x636e,0x81e8,0x9886,0x2693,0x70c8,0x4f38,0x7ec4,0x8c5a,0x626b,0x9669,0xae40,0x6362,0x8d24,0x83f2,0x517c,0x5951,0x7b52,0x8305,0x95d8,0x990a,0x8b,0x192,0x53d8,0x6e9d,0xff47,0x5009,0x84dd,0x8d08,0x51b3,0x51cd,0x5f84,0x6050,0x62ab,0x6c99,0x7576,0xb8,0xff3a,0x90,0x6676,0x67f4,0xff44,0x58c1,0x5458,0x5de8,0x8d28,0xbd88,0x4ece,0x8aa4,0x7db2,0xc558,0x5c08,0xc0bc,0xb9dd,0x642d,0x8584,0x6316,0x71c3,0x78bc,0x9a71,0x5f93,0x7267,0x698,0xff27,0x6309,0x6804,0x6c92,0x9818,0x8b0e,0xbc,0x69fd,0xc628,0xc98c,0x8fea,0xff35,0x9e7f,0x4f9d,0x9f99,0xd2b9,0x8d4f,0xbe14,0x5bdf,0x5f3a,0x6052,0x68c0,0x6dbc,0xbe,0x7ea6,0x8a13,0xd568,0x9519,0xd569,0x5869,0x968a,0x5ba3,0x5c01,0x6838,0x8a31,0x9910,0x541b,0xb978,0x67c4,0x7e04,0x5e7b,0xb7fd,0xcb48,0x8150,0xff52,0x7720,0xff20,0x4e39,0x6d45,0x6163,0xbca0,0x9b3c,0x75c7,0x626e,0x62b1,0x12f,0x628a,0xd328,0x3a4,0x5e7e,0xff4b,0x25c7,0xaa,0xcef4,0x602a,0x6d6a,0x79e4,0x8ab2,0x307d,0x5340,0x6635,0x5e36,0x5acc,0x6a23,0x148,0x97,0x8da3,0x98fe,0x600e,0x8fde,0xbabb,0x5f66,0xb3cc,0xd074,0x5fb3,0x6297,0x93e,0x5264,0x56f0,0x7df4,0x8ba2,0xbd81,0x3007,0x30cc,0x6d99,0xd615,0x4e32,0x6756,0xb984,0xd0b9,0x25ab,0x5bf5,0xc139,0x2010,0x521a,0x61f8,0xd5a5,0x7c8b,0x82ae,0x2c8,0x66fe,0x64f,0x5f18,0x8352,0x8bc9,0xb530,0x1,0x60b2,0x66b4,0x42b,0xff9e,0x51e6,0x6319,0x7c89,0x589e,0x8111,0x5fcd,0x4e71,0xff9d,0x79df,0x7dba,0x9038,0x51c4,0x64d,0x696a,0x7a40,0x5be7,0x9b42,0xff54,0x9177,0x9cf4,0x65e7,0x5c0d,0x8fa6,0x5386,0x5439,0x92fc,0x9876,0x42e,0x6368,0x82af,0x624,0x67d3,0x6e56,0x6ede,0x80a9,0x5de7,0x62d2,0x8ba1,0x226a,0x53eb,0x226b,0x9633,0x987e,0x6279,0x7126,0xbcc0,0xd3ed,0x732e,0x6691,0x62fc,0x6f2c,0x219,0x987b,0xbc1b,0xc0c8,0xc874,0x670b,0x4e14,0x53ec,0x55ae,0x962a,0xcd1d,0x5b99,0x93e1,0x5510,0x6cf0,0x7a74,0x8b6f,0xc838,0x502b,0x5091,0x5144,0x91c7,0xc708,0x5211,0x5b22,0x5fe1,0x6597,0xac1d,0xc561,0x5e8f,0x62bd,0x6db2,0x75b2,0xba3c,0xc5d1,0x8fc5,0x9298,0xd65c,0x4e3d,0xac80,0xc55e,0x6ee1,0xafb8,0xce68,0xe33,0x6d6e,0xae09,0xff38,0x40b,0x6ea2,0x80a1,0x90f7,0x95c7,0x866b,0x89e6,0x4ec5,0x585e,0xc0c9,0xcc38,0x5256,0x96f7,0x53e6,0x64cd,0x7e70,0xb108,0x5371,0xce20,0xd655,0x200e,0xbd09,0x5375,0x5b54,0xd3c9,0x6591,0x804c,0x9154,0xb860,0x4ea1,0x83ca,0x96ea,0x640d,0x6f3,0x54ea,0xb9bf,0x12e,0x679d,0x5f48,0x6850,0xc808,0x4f5b,0x6d1b,0x8010,0x89c9,0xb290,0x54e6,0x6e09,0xb78c,0x62f3,0x8207,0x8aaa,0x651,0x2015,0x582a,0x62fe,0xc721,0xd48d,0x5e16,0x5036,0x6c23,0x202c,0x4ec1,0x513f,0x719f,0xb79c,0x5360,0x8bca,0xcc44,0x7dbf,0xc54c,0x6de1,0x5bd2,0x9903,0x8499,0xe,0x526f,0x5c3b,0x8fdc,0x9ede,0x88c1,0x89c0,0x59c6,0xc637,0x6bbf,0x9375,0xd32c,0x56c3,0x7b4b,0x8155,0xc9f1,0x65e8,0x6682,0xd608,0xb610,0xccad,0x4ecf,0x656c,0x76d1,0xba38,0x50ac,0x8fb9,0x5ee3,0x7edd,0xbd04,0x4efd,0x5356,0x6566,0x7b26,0x7b51,0x8fc4,0xff4c,0x68d2,0xb208,0xc5b8,0x4e66,0x7965,0x8d41,0x627e,0x6b20,0x388,0xc600,0x5218,0x59bb,0x65e2,0x67cf,0x90a6,0xbc8c,0x26a,0x6377,0x7c92,0x6236,0x8f9b,0x584a,0x72d9,0xaed8,0x654f,0x8b21,0x8d05,0x9d28,0xd0c8,0x702c,0x76d7,0x39a,0x7761,0xc9c8,0x658e,0x842c,0xd5d8,0x707d,0xc5d8,0x25b,0x62e0,0x5f90,0x8aa0,0xb2cc,0x6c5a,0x8108,0x9f62,0x7232,0x5374,0x5b8f,0x5fb4,0x932c,0x70cf,0xd734,0xc8,0x67b6,0xe1b,0x3012,0x6e7f,0x907f,0x68da,0x7372,0x8ca7,0x8dd1,0x9a12,0x170,0x5403,0xb7fc,0x8df5,0x5e6b,0x8cbc,0xad70,0xbc1d,0xbdf0,0x7ef5,0xff42,0x46a,0x690d,0xd4,0xc6c0,0x52c7,0x7473,0xb80c,0x5076,0x6bd2,0x2588,0x5800,0x718a,0x808c,0xc5c4,0x7a93,0x5c65,0xff9f,0x92b7,0x309c,0x5bbd,0x9811,0x9f13,0x4f17,0x4fca,0x4fe3,0x5382,0x6589,0x690e,0x81a8,0x9694,0x8cdb,0xb410,0x6fa4,0x5757,0x88e1,0xd9,0x5f9e,0x723e,0x8302,0x8f6e,0x952e,0xb809,0x59d0,0x6fc3,0x7de0,0x4e3c,0xaca0,0xff0a,0xff70,0x82,0xd765,0x21b,0x76d8,0x7a3d,0x8be6,0xc05c,0xcf00,0x279,0x92e,0x5c42,0x80a5,0x9591,0xd669,0x4e49,0x5e86,0x8138,0x9ebd,0xcfe0,0x61d0,0x73e0,0x970a,0xc88b,0x7e2e,0x5609,0x651d,0x2030,0x4e24,0x503c,0x51a0,0x6012,0x8a02,0x8c22,0xc545,0x4ead,0x5353,0x5e84,0x62dd,0x723d,0x8b93,0x9690,0xe09,0x53e5,0x72d7,0x9ece,0xc1a1, 60 | 0xe46,0x6841,0x5ef6,0xb9de,0x4eb2,0x59eb,0x5c14,0x8428,0x9663,0xc2f1,0x5f13,0x7956,0x9a8c,0x6aa2,0x94a2,0x98fc,0x9ea9,0x63c3,0x804a,0x829d,0xe0a,0x2033,0x9304,0x932f,0xc9d5,0x1a,0x143,0x4ee4,0x538b,0x52bf,0x58ca,0x6a31,0x8d1f,0x8df3,0xc2b4,0xd544,0xf0,0x7092,0xbcc4,0x11c,0x7802,0x99c6,0xac78,0xf713,0x9063,0xb828,0xff37,0x64c,0x5475,0xb4e0,0xc220,0xd658,0x5740,0x9670,0xbcd1,0x7d93,0xbc31,0x273f,0x5104,0x6383,0x680f,0x6a8e,0xadfc,0x9b,0x706f,0x75be,0x7a7f,0x8d27,0x8f1d,0xae38,0xcef5,0x60a9,0x8a34,0xb378,0xc368,0x5fe7,0xad11,0xff50,0xe4c,0x9283,0xaf,0x4e59,0x504f,0xb780,0x3be,0x7cd6,0x7d1b,0x51e0,0x55dc,0x6016,0x8be2,0xc0b4,0x5283,0x8a98,0x8caf,0xd76c,0x511f,0xb9b4,0x6811,0xc816,0x9d,0x4e60,0x5c16,0x6548,0x6ff1,0xb137,0xc6c3,0x686,0x5b5d,0x7652,0x805a,0x4fb5,0x52b2,0x5a01,0x2c7,0x4f73,0xcf58,0x91,0x200b,0x515a,0x5885,0x6578,0xb192,0xd1a4,0x5996,0x5bfb,0x5e01,0x626c,0x811a,0x9002,0x9178,0xbc00,0xc11d,0x6602,0x79bb,0x8a23,0x97e9,0xc5d4,0xe39,0xd15c,0xb839,0xc84c,0x4ebf,0x52aa,0x8b72,0x7a0d,0x90ed,0x9678,0x5716,0x5851,0x6247,0x6d78,0x7130,0x790e,0x67a0,0x7238,0x96be,0x5974,0x684c,0x6cea,0x99c4,0x5c48,0x61c2,0xc7c1,0x25a1,0x5e1d,0x6c64,0xc5bc,0x614e,0x6ed1,0x5750,0x9677,0x50be,0x5fd9,0x6062,0xe13,0x54b2,0x6753,0x6c60,0xbc97,0x50da,0x5fb9,0x92ed,0xb4e3,0x397,0x7363,0xcd2c,0x70e7,0x80c6,0xbba4,0x3043,0x771e,0x7bc4,0x8cab,0xff48,0x5956,0x5c90,0x67d0,0x9655,0xca,0x6367,0xafbc,0xc2b9,0xc625,0xd68d,0x68a6,0x935b,0xc871,0x3047,0x4e43,0x5b69,0x5b83,0x6284,0x8cd1,0x8d37,0x949f,0xc0ad,0x63e1,0x8f83,0x77ac,0x8475,0x8f9e,0x9418,0x94fe,0xd611,0x4e4f,0x4e9c,0x809d,0x9162,0x689d,0x6b8a,0xb4a4,0x930,0x50f9,0x53c3,0x56e2,0x6fc1,0x9e93,0x5c0a,0x5cef,0x609f,0x6c57,0xc57d,0xd300,0x4f75,0x81,0x4e22,0x59da,0x6ec5,0x96f2,0x9ed9,0x58a8,0x6000,0x756b,0x7e26,0x84b8,0x85a6,0xaddc,0xb77d,0xd754,0x819c,0x88ad,0x94f6,0xb728,0x5fe0,0x6109,0x78e8,0x86db,0xd0dd,0x7532,0x9042,0x9644,0x5212,0x5a1c,0x5b78,0x15c,0x575b,0xb2f5,0xc5fc,0x10e6,0x5618,0x5c4f,0xff55,0x5174,0x533f,0x6021,0x8f7b,0xaca8,0x1c,0x9c,0x72ed,0x8058,0x82b3,0x8e0f,0x9738,0x5100,0x5320,0x54c0,0x60a3,0x7ef4,0x81fa,0x84ee,0x8c01,0xc7a1,0x4eae,0x5192,0x5f26,0x6b0a,0x6dcb,0x7d2b,0x8bad,0xb274,0x5be6,0x8303,0x9065,0xb118,0x40c,0x5b9c,0x675c,0x6b61,0x733f,0x78c1,0xcc29,0xd050,0x599e,0x8dfb,0xc9f8,0x55ab,0x68cb,0x76d6,0xb9bd,0xcda9,0x51b0,0x8b19,0x8c4c,0x8f2f,0x559d,0x596e,0x9271,0x9510,0xc7a0,0xd4e8,0x266f,0x6291,0x8a69,0x6094,0x7334,0x81fb,0xae34,0xc5b5,0xcd95,0x938,0x6606,0xb2c9,0x596a,0x75ab,0xbc0f,0x51e1,0x66dd,0x8ce2,0x9867,0xd07c,0x4e80,0x85fb,0x9992,0xc90c,0xcc45,0x5854,0x8bb2,0x53e2,0x57f7,0x6232,0x9884,0x990c,0x51dd,0x8a72,0xbf55,0x6355,0x6da8,0x906d,0xc228,0x4ea6,0x708e,0x7434,0x8718,0x6a6b,0xcca0,0x907,0x54cd,0x6b04,0x7dad,0x806f,0x81d3,0x95f2,0xb2dd,0x7099,0x8b90,0x987a,0xccab,0xd6a8,0x94b1,0x9957,0x5976,0x6daf,0x732a,0x7e4a,0xc798,0x76c8,0x7f85,0x8521,0x50e7,0x77e2,0x9262,0xc811,0xd614,0x91f,0x575a,0x5c3c,0x6f64,0x8e0a,0xc724,0x840c,0x8cbf,0x9646,0x88dd,0xbf40,0xc528,0xd5e4,0x5251,0x52d8,0x5be9,0x6230,0x6dfa,0x7855,0x96c7,0xd038,0x5f81,0x6f02,0x8266,0x9685,0x9f0e,0xbb35,0xff46,0xe28,0x5462,0x5b64,0x62b9,0xce78,0xd601,0xff72,0x51b2,0x54c8,0x5c3a,0x7e4b,0x975c,0xc61b,0x2c6,0x25bd,0x90ca,0x9e23,0xb05d,0xb304,0xb807,0xbc40,0x5047,0x5ec9,0x5f6c,0x6653,0x7be0,0x9810,0x5169,0x52a3,0x6731,0x90aa,0x986f,0xb4b7,0x20b4,0x5049,0x8d62,0x95fb,0xc751,0x5152,0x67d4,0x7d2f,0x80de,0x8d5b,0x9970,0x616e,0x6176,0x7977,0x89c4,0x5f02,0x6768,0x6cb8,0x9f20,0xff7b,0xc0f5,0x9f,0x915,0x5200,0x60e0,0x6ef4,0x7950,0x7eed,0x8b83,0x8bd7,0xace8,0xbe57,0x8017,0x4ff3,0x574a,0x7e3d,0x68b0,0x8107,0x91dd,0xc8e0,0xd150,0x5c3f,0x5e81,0x6458,0x6f01,0x6f5f,0x73af,0x845b,0x9192,0xce21,0x11b,0x59c9,0x5f0a,0x81b3,0x9047,0xc904,0xff71,0xff7a,0xcf,0x59dc,0x6f58,0x9eba,0xb9e1,0x25c4,0x5265,0x82bd,0x8dc3,0x9bad,0x514e,0x519b,0x5857,0x707c,0x82cf,0x886c,0x8f29,0x9905,0x24b6,0x4f0d,0x54a8,0x566c,0x5a46,0x6389,0x7ec3,0x854e,0x3013,0x6742,0x6d12,0x88c2,0xb298,0xd56d,0xd575,0x5984,0x5ec3,0xb420,0x6d69,0x6fb3,0x9879,0x4fc3,0x5524,0x5ac1,0xac08,0xd798,0x399,0x4ef0,0x5132,0x84cb,0xb7c9,0xc655,0xd2c0,0x552f,0xc30d,0x548f,0x598a,0x5e05,0x6960,0xcee8,0xd0c4,0x303,0x56da,0x5d07,0x613f,0x7687,0x7eaa,0x8b5a,0x4fa6,0x517b,0x6687,0x80ba,0xc2f6,0x5c0b,0x65e6,0x6817,0x7ee7,0x80c3,0xd639,0x4eee,0x5b59,0x6065,0x61a7,0x6469,0x64a4,0x6c37,0x6e0b,0x390,0x3049,0x55ce,0x6d59,0x88f8,0x99b4,0xc140,0xd53d,0xd63c,0x75af,0x8209,0x8c08,0x25b3,0x63ed,0x64c1,0x90d1,0x9f3b,0xc0e4,0xd154,0x589c,0x5e7d,0x60f9,0x6212,0x6234,0x66d9,0x6df5,0x731b,0xbab8,0x4f2f,0x4f51,0x5146,0x543b,0x6444,0x7e2b,0x7f18,0x8ddf,0x8fbb,0x508d,0x6607,0x7d46,0x8986,0xc695,0x4f3a,0x507d,0x73ea,0x901b,0x908a,0xb9bc,0x14d,0x16f,0x45b,0x60dc,0x66a2,0x8c28,0x8e48,0xc529,0xd3f0,0xff89,0x4e4e,0x4f19,0x5beb,0x65d7,0x7ec7,0x8a89,0xb958,0xcc3e,0x4f34,0x5bdb,0x63d2,0x6e15,0x6eb6,0x7bee,0x2248,0x6167,0x665a,0x8972,0xad34,0xbc94,0xc26c,0x4fd7,0x6a13,0x7cde,0x91c8,0x98fd,0xbc0d,0x2660,0x76fe,0x9986,0x9c7c,0x51b5,0x56f4,0x58c7,0x5c81,0x62b5,0x91dc,0xbe48,0x54b3,0x6020,0x4fa0,0x5e3d,0x68a8,0xb08c,0xc2ac,0xcc3d,0x4e34,0x6b3a,0x7c97,0x8170,0x8b00,0xbd99,0xc654,0x5448,0x611a,0xff61,0x4e1d,0x4e25,0x50b3,0x5bc2,0x8015,0xccd0,0x5a9b,0x6784,0x5b81,0x5d29,0x5e06,0x64d4,0x8c8c,0xb2f4,0xb86f,0xba87,0xd5c8,0xff8f,0xe1c,0x60a6,0x7075,0x7545,0x7e01,0x904d,0x9eb5,0xd2bc,0xfe80,0x5706,0x5c24,0x6842,0x6c47,0x6e67,0x72fc,0x7766,0x7a42,0x9aee,0xb0ac,0x53f9,0x543e,0x77b3,0x7e8c,0x8cb0,0x8d38,0x45c,0x5263,0x5939,0x5d50,0x7f72,0x8431,0x9234,0xb5a8,0xd64d,0x50bb,0x79ef,0x8ed2,0x90e1,0xff8c,0x6c1,0x62e5,0x64f4,0x7adf,0xacac,0x6a02,0x74f6,0x8bc6,0xbe60,0xff7d,0x64b2,0x6ecb,0x95a3,0xc6e8,0x4f1f,0x5642,0x586b,0x5983,0x7985,0x7db4,0x80dc,0x81e3,0x8a17,0x60ca,0x633f,0x7164,0x83b7,0x862d,0x8a87,0xbfd0,0x40e,0x591f,0x65ac,0x6c40,0x7a32,0x8650,0x989c,0x558b,0x5ac9,0x86c7,0xd314,0x58ee,0x5987,0x5de1,0x61a9,0x6328,0x64da,0x6562,0x867d,0xb5bb,0xb838,0x9be,0x200f,0x62f6,0x6b6f,0x6f84,0x721b,0x74dc,0x8d66,0x9676,0xff84,0x6b23,0x8c13,0x8d4e,0x9ebc,0xbab0,0xd070,0xd3e,0x59ac,0x5f52,0x67f3,0x6c70,0x7409,0x77db,0x7eb2,0x8d8b,0x2009,0x5cb3,0x706d,0x70b8,0x8997,0x9396,0xac16,0xff76,0xff7f,0xe36,0x5a2f,0x77ff,0x7b5b,0x9ea5,0xad74,0xadc0,0xb123,0xb835,0xff80,0x100,0x2dc,0x452,0x200c,0x5d8b,0x6876,0x8276,0x9640,0xcf64,0x546a,0x5f70,0x639f,0x64c7,0x6bc1,0x7070,0x84c9,0x88b4,0x94ed,0x961f,0x1e29,0x2591,0x51e4,0x542f,0x90ae,0xe18,0x6b77,0x7d10,0x8ca2,0x5b55,0x5bee,0x80af,0x92c7,0xcc30,0x2011,0x52de,0x5377,0x5410,0x68b6,0x6cbc,0x7984,0x7cf8,0x820d,0xc95,0x51cf,0x54e5,0x5c9b,0x5f39,0x6f54,0x72d0,0x72e9,0x7be9,0xc783,0xd6c8,0xacb,0x5805,0x6905,0x751c,0x7656,0x7dbe,0x8a3b,0xc81d,0xcabd,0xcd98,0xff77,0x5075,0x537b,0x60a0,0x7275,0x7dfb,0x88c4,0xb193,0xd478,0x5821,0x6349,0x65fa,0x6cf3,0x7cca,0x7e6b,0x96b7,0x978d,0x989d,0xb5a0,0x3a9,0x5440,0x68c4,0x74a7,0x76e1,0x7eaf,0x806a,0x8212,0xbbf9,0x45e,0x6068,0x67f1,0x6fe1,0x722c,0x7344,0x96b1,0x9706,0x9c24,0xb7a8,0xb86d,0xcc0d,0xd2f4,0xd305,0x45f,0xa95,0x4e9e,0x5442,0x820c,0x84bc,0x84c4,0x9592,0x9a0e,0x9a30,0xd02,0x4e30,0x53f6,0x5eca,0x65cb,0x6a58,0x7827,0x7a6b,0x93ae,0x983b,0xc5c7,0xd0ac,0x6de,0x2207,0x5617,0x5e4c,0x64f7,0xc989,0xe47,0x2266,0x55a9,0x63fa,0x6d82,0x827e,0x8363,0x838e,0x87a2,0x89ba,0x8b5c,0x9526,0x9636,0x9f50,0xce6d,0xd480,0xff3c,0xa88,0x5949,0x5faa,0x66ab,0x7891,0x7d62,0x8bfe,0x9ca8,0xb113,0xb465,0x134,0xca0,0x2103,0x2620,0x2727,0x5733,0x658c,0x7a00,0xbdd4,0xd32,0x5eb5,0x6089,0x62d3,0x635c,0x76bf,0x7c98,0x49a,0x61f7,0x64b0,0x7d6e,0x8a50,0xb0b8,0xbca4,0xc27d,0xc568,0xd61c,0xff59,0x49b,0xaae,0x5167,0x51ef,0x5de3,0x6803,0x6a0b,0x6bd5,0x6ce5,0x7f3a,0x905c,0x54ed,0x55e3,0x5674,0x5c4d,0x6f0f,0x6f20,0x9010,0x9274,0xace1,0xb7ab,0xd640,0x39e,0x61b,0x307a,0x51f9,0x5606,0x6258,0x676d,0x695a,0x6eff,0x71c8,0x865f,0x8865,0x9855,0xcce4,0x102c,0x30f1,0x694a,0x7e3e,0x80f6,0x8154,0xb7ad,0x2003,0x2267,0x3062,0x538c,0x6447,0x67ff,0x6ce1,0x75fa,0x7c9f,0x8328,0x8870,0x8cfd,0xb8f9,0xd2f1,0xff8a,0x561b,0x6734,0x6b86,0x7199,0x75e9,0x76c6,0x7a3c,0x7b87,0x7d27,0x8299,0x87f9,0x8912,0xb0d0,0xb150,0xc5bb,0xc775,0xd0c1,0xd600,0x83,0x10d0,0x5899,0x5954,0x5c6c,0x71d5,0x820a,0x94bb,0xacbc,0xb17c,0x125,0xd4d,0x30c2,0x4f24,0x541f,0x5988,0x5fc6,0x6893,0x6a3d,0x828b,0x9aea,0xb790,0xbd24,0x2461,0x52ff,0x7d55,0x86cb,0xb799,0xc190,0xc9dc,0x8f,0x152,0x51f0,0x570d,0x5751,0x7eff,0x8d35,0x91b8,0x9e4f,0xb110,0xb5a4,0xc13c,0xc6e0,0xd758,0xd2e,0xe24,0x2661,0x5565,0x5c09,0x6115,0x63b4,0x80a0,0x9022,0x459,0x45a,0xd2f,0x5566,0x59a5,0x6446,0x7425,0x7a31,0x8d26,0x1eaf,0x587e,0x5f77,0x6249,0x64e0,0x6865,0x6e9c,0x73c0,0x73c8,0x7de9,0x819a,0x8537,0x8ce3,0x9ac4,0xc0b6,0xc194,0xcc2c,0xff56,0x5edf,0x631f,0x6d1e,0x7e7c,0x7f36,0x902e,0x95ca,0xb07c,0xb367,0xb840,0x146,0x10d8,0x2764,0x8a93,0xc4f0,0xd3d0,0x408,0x6f4,0x10da,0x51cc,0x57a3,0x62ff,0x73b2,0x81b5,0x8e29,0x8fb0,0x92ad,0xc2b7,0xce60,0x5f04,0x632b,0x7840,0x7947,0x920d,0xac14,0x5eb8,0x6851,0x6a94,0x751a,0x8f44,0x91ca,0xae68,0xbc38,0xd134,0xd78c,0xcb,0x6302,0x7ecd,0x837c,0x8b49,0x8d50,0x8ef8,0xbe59,0xbe7c,0xc794,0xcc,0x327,0x540a,0x570f,0x59ae,0x5a04,0x6c50,0x6c6a,0x840d,0x8a6e,0x9760,0x9a19,0xbca8,0xc564,0x38f,0x30f2,0x4eff,0x6076,0x6f70,0x7b39,0x871c,0x8ba8,0xbd10,0xc554,0xd39c,0xff78,0x10d7,0x10e0,0x2642,0x50a8,0x53e9,0x5766,0x5920,0x5c51,0x72a0,0x773e,0x7ed8,0x7f50,0x8178,0x8cd3,0x901d,0x9061,0x955c,0xaef4,0xb0ae,0xc728,0xcea1,0x179,0x935,0x2162,0x4fc4,0x5242,0x5451,0x5723,0x6df3,0x8072,0x9521,0x9837,0xb904,0xbc24,0xc1fc,0x150,0xabe,0xd33,0x2460,0x4e58,0x4e61,0x5a3c,0x5efb,0x6eda,0x84a1,0x8dcc,0x96a8,0xad81,0xb864,0xd3fc,0x5219,0x53a8,0x5761,0x5893,0x5ef3,0x60e8,0x624e,0x6627,0x6d2a,0x7345,0x76d2,0x7eba,0x82d7,0x8fa8,0xb458,0xb9c1,0xba39,0xc6c5,0xc998,0xc9d3,0x6015,0x65ed,0x764c,0x79ae,0x7c60,0x8c9d,0x9285,0x96d5,0x9dfa,0xade0,0xaf3d,0xb6f0,0xff97,0xffe3,0x2229,0x642c,0x64e6,0x6a59,0x6d9b,0x78a7,0x7e1b,0x8b6c,0x8c9e,0x95f9,0x96d6,0x932,0x4e4c,0x5203,0x526a,0x5302,0x5962,0x5f7f,0x618e,0x643e,0x8338,0x885e,0x8d5a,0x95ea,0xb538,0xcf30,0xd3bc,0xff9a,0x5141,0x517d,0x659c,0x6670,0x7011,0x730e,0x7b28,0x8f69,0x9093,0x94c1,0x9673,0x9761,0xac90,0xb78d,0xca8,0xdd2,0x5634,0x70e6,0x7551,0x7ca7,0x7f1d,0x865a,0x8af7, 61 | 0x96eb,0xb4dd,0xb529,0xb9f9,0xc6b1,0xf8ff,0x308,0x407,0x924,0x92d,0x6155,0x619a,0x660c,0x674f,0x6f94,0x73ba,0x7ed1,0x8292,0x8861,0x8d21,0x907c,0x98d8,0x9972,0xb4ef,0xc130,0xc314,0xc787,0xc8fd,0x52b1,0x5782,0x71df,0x742a,0x7432,0x7d18,0x8389,0x963b,0x9665,0x96dc,0x9896,0xb2d0,0xb7ed,0x10e3,0x279a,0x50c5,0x54c9,0x5e63,0x63aa,0x7235,0x786b,0x816b,0x85aa,0x8607,0x90c1,0xc635,0xc880,0xd3f4,0x203c,0x2462,0x51f8,0x5968,0x6e07,0x7272,0x789f,0x8105,0x85ab,0x86ee,0x8776,0x9326,0x987f,0x99d2,0xb3c8,0xb3fc,0xcf8c,0xd761,0x87,0xab8,0x10e5,0x4e8f,0x54aa,0x61c7,0x6b6a,0x717d,0x7336,0x7897,0x7a9f,0x7ca4,0x817e,0x8de8,0x8f89,0x9547,0x9583,0x961c,0x9635,0x9bdb,0xff5d,0x110,0x154,0x223c,0x5434,0x545f,0x559a,0x55aa,0x6325,0xb7b5,0xb8f8,0xbbff,0xc168,0xcc99,0xff6f,0xf7,0x1a1,0x3a7,0x9b2,0x2564,0x4f54,0x5413,0x558a,0x5a49,0x8702,0x895e,0x8cca,0x9813,0x9d5c,0x9e1f,0xb429,0xcf5c,0xd0d1,0xd610,0xff9b,0x13d,0xacd,0x57c3,0x5986,0x64a5,0x66d6,0x6866,0x722a,0x7a1a,0x814e,0x8a0a,0x8b33,0x8d75,0x919c,0xac11,0xbc45,0xd138,0x2566,0x53a6,0x59a8,0x6276,0x62dc,0x65fb,0x66c6,0x6cdb,0x7329,0x79e6,0x83b2,0x83cc,0x8d76,0x8f49,0x900d,0x91a4,0x94c3,0xb0c8,0xba40,0xc149,0xff83,0xccd,0x272a,0x5496,0x5504,0x5944,0x5a9a,0x5f03,0x6101,0x680b,0x7eb8,0xcb49,0xcde8,0xff7c,0x302,0xabf,0x545c,0x5835,0x5bf6,0x5e9f,0x6182,0x6270,0x7015,0x7433,0x7a83,0x7c9b,0x807d,0x8096,0x8511,0x85dd,0x96f6,0x9776,0xb04c,0xba5c,0xcf1c,0xff5b,0xff8e,0x949,0x1ea3,0x51b4,0x52ab,0x55b0,0x5bab,0x6293,0x7261,0x773a,0x7aae,0x7b94,0x8358,0x83f1,0x8d3e,0x9634,0xada4,0xbc16,0xc2a8,0xc6f9,0xd280,0x1b0,0x304,0x5b4,0x920,0xcbf,0xe0b,0x1019,0x2463,0x279c,0x5815,0x5958,0x5bc5,0x60da,0x6492,0x69ae,0x6b72,0x6d89,0x6fe4,0x7262,0x7729,0x7949,0x7c3f,0x7d79,0x821f,0x8230,0x8304,0x88fe,0x8cb6,0x8d1d,0x95c6,0xad73,0xb180,0xb364,0xb4c0,0xc824,0xd380,0xff98,0x88,0xaa8,0xc41,0xc9f,0xcaf,0xf0b,0x1d52,0x5269,0x5937,0x62d8,0x71d2,0x7832,0x809a,0x8d95,0x97e7,0x9812,0xae0d,0xc12d,0xd004,0xd29c,0xff99,0xcb0,0x2047,0x4f10,0x51af,0x6263,0x6681,0x6db5,0x71ed,0x723a,0x72d2,0x7e6a,0x8166,0x8339,0x8d74,0x8f14,0x8ff9,0x97ad,0x9f84,0xb00c,0xb454,0xb4ed,0xb960,0xbaac,0xc2f8,0xd17,0x202f,0x21b5,0x507f,0x5197,0x532f,0x57d4,0x67ef,0x6dd8,0x6ee8,0x70ef,0x7463,0x7a33,0x7fe0,0x80ce,0x810a,0x895f,0x8f15,0x8fbf,0x91e7,0x96c0,0xafc8,0xc9d0,0xff93,0x8c,0xc6,0x2bc,0x1ecb,0x1ed3,0x5077,0x51a8,0x5415,0x60ef,0x622a,0x633a,0x6dc0,0x6fe0,0x710a,0x758e,0x8036,0x8061,0x8113,0x817a,0x81bd,0x857e,0x8bef,0x9488,0x95ed,0x9727,0x9eb9,0xc52c,0xd1b0,0xd1f4,0xff3f,0x263c,0x574f,0x5ff1,0x621a,0x6442,0x75f4,0x7960,0x7d21,0x8afa,0x8e2a,0xac24,0xb8b0,0xb8fd,0xc15c,0x937,0xc9c,0xdc4,0x2513,0x4eea,0x52c3,0x55da,0x5824,0x5a1b,0x6267,0x65c1,0x6795,0x70ae,0x739b,0x75b1,0x7f06,0x8151,0x8247,0x82fa,0x874b,0x8bf1,0x916c,0x92ea,0x9501,0xb9db,0xd0d5,0xd540,0xd56b,0xa9f,0xcb5,0xcbe,0x3045,0x309b,0x4e27,0x4f7c,0x519c,0x536f,0x53d4,0x5b9b,0x635f,0x67af,0x7063,0x7def,0x7e55,0x80f4,0x83e0,0x8a1f,0x8d60,0x8f88,0x9c2f,0xb0e5,0xd750,0xff64,0x543c,0x5507,0x5631,0x5e18,0x61f2,0x6775,0x68af,0x7325,0x7b48,0x7cb5,0x82b7,0x9077,0x9080,0x9132,0x9190,0x9b31,0xb0bc,0xb35c,0xb7b4,0xb801,0xb9e5,0xba4d,0xcc54,0xcf04,0xd0f1,0xd5ec,0x19,0x129,0x221a,0x3003,0x4fa7,0x51a5,0x67dc,0x70c2,0x7791,0x7e82,0x8327,0x884d,0x8b39,0x8fbd,0xb2e5,0xb2ee,0xb8f0,0xc5c9,0xc88c,0xf020,0xe2f,0x2025,0x52f2,0x555f,0x5589,0x5718,0x5806,0x59d1,0x5a05,0x5c1d,0x5fcc,0x6241,0x62d9,0x67aa,0x6adb,0x7adc,0x7b20,0x7eb5,0x803d,0x80a2,0x812b,0x8463,0x846c,0x8823,0x8c31,0x9057,0xae4a,0xc598,0xccbc,0xd508,0xd5cc,0xff81,0xff92,0x22c5,0x4f88,0x51c9,0x5384,0x5395,0x53e1,0x594b,0x614c,0x6190,0x65a4,0x6668,0x6808,0x70bc,0x72b9,0x73ca,0x7504,0x956d,0x9784,0x9913,0xb084,0xb518,0xba58,0xbe4c,0xc555,0xd31d,0xd3ad,0xd578,0xff82,0x429,0x982,0x9ac,0x5118,0x5239,0x52d2,0x53d9,0x5561,0x57ab,0x5b5c,0x66f9,0x7538,0x76f2,0x7fe1,0x8083,0x8fc8,0x9059,0x94a9,0xb0af,0xb20c,0xbcbd,0x8d,0x6d2,0x1ea1,0x2666,0x30f5,0x339e,0x572d,0x60df,0x6170,0x6846,0x7058,0x800d,0x83ab,0x90af,0x918d,0x99a5,0x9c9c,0xadc4,0xb0c9,0xb2d8,0xc14b,0xcda4,0xff73,0x92f,0x220e,0x2252,0x5398,0x5f6b,0x6652,0x66a6,0x6bbc,0x6e20,0x7169,0x775b,0x7fc1,0x8ecc,0x9699,0x96aa,0xb054,0xb2d9,0xb744,0xba4b,0xbe68,0xc78a,0xc9e4,0xd2,0x30c,0x6aa,0x941,0x565b,0x5dfe,0x6323,0x633d,0x660f,0x6c89,0x6cab,0x6f6d,0x731c,0x74e6,0x788e,0x7dde,0x82a5,0x837b,0x906e,0x9601,0xb099,0xb819,0xc559,0xc62e,0xc735,0xd648,0xff7e,0x98,0x94b,0xd3f,0x1fdf,0x56c1,0x59be,0x5f17,0x5ffd,0x6148,0x62c6,0x62e8,0x64bc,0x6643,0x6e1a,0x6edd,0x7237,0x7460,0x7cad,0x7ed5,0x7fa1,0x8106,0x81c9,0x82a6,0x82d1,0x83e9,0x8513,0x8bc8,0x8c26,0x8d14,0x8d2e,0x93c8,0x996e,0x9b06,0xaf2d,0xc1c4,0xc651,0xc92c,0xcca8,0xcfe1,0xff,0x14c,0x305,0x352,0x396,0x5016,0x55dd,0x57b0,0x5bb5,0x5be8,0x5cac,0x64ce,0x6897,0x698e,0x6f80,0x70e4,0x7560,0x77ee,0x79c9,0x7c95,0x7f70,0x8000,0x81c2,0x82db,0x8888,0x88d4,0x8987,0x8f68,0x9306,0x966a,0xacfd,0xad49,0xbb44,0xbf51,0xc058,0xc300,0x342,0x4d1,0xd30,0xf72,0x4e11,0x51c0,0x53f1,0x54ac,0x54bd,0x5875,0x58fd,0x5b6b,0x5ce0,0x5ef7,0x620e,0x658b,0x685d,0x6b96,0x6beb,0x714c,0x7682,0x7709,0x77ef,0x7cc0,0x7fc5,0x81a9,0x826e,0x840e,0x919b,0x99d5,0xe0e,0xe1f,0xf7c,0x1014,0x2161,0x51db,0x51fd,0x58d3,0x7009,0x7089,0x7405,0x7573,0x7881,0x7889,0x7a77,0x7aff,0x7f69,0x80d6,0x82d4,0x8387,0x84ec,0x8783,0x88df,0x8b80,0x8d0f,0x91ac,0x9322,0x94dc,0x96d9,0x9a57,0x9c88,0xb048,0xbe10,0xc500,0x1d,0x42a,0x490,0xdb1,0x2580,0x50b2,0x5154,0x5385,0x5495,0x5a7f,0x5bec,0x6070,0x62ed,0x6746,0x6881,0x68d5,0x6988,0x6ac3,0x6f47,0x70df,0x74ca,0x7750,0x77ad,0x7978,0x7b4d,0x7cb9,0x7de3,0x7ef3,0x7f62,0x86d9,0x8f9f,0x95f5,0x9c81,0xb04a,0xb7f4,0xcc0c,0xd0a8,0x169,0x2501,0x2765,0x314b,0x54af,0x5614,0x573e,0x5c53,0x5e9e,0x5f61,0x62d4,0x69cd,0x6e85,0x72c4,0x7da0,0x7ed2,0x8367,0x8590,0x8774,0x886b,0x8bf8,0x98d9,0xaf43,0xb8ec,0xbc25,0xc887,0xcd0c,0xce35,0xcea3,0xd1b1,0xfe41,0x11e,0x6ba,0xd2c,0x103a,0x4f47,0x4f69,0x50a3,0x55b7,0x5783,0x5c18,0x5d5c,0x6168,0x62a2,0x6f5b,0x734e,0x7422,0x788d,0x7dbb,0x7eb9,0x82f9,0x8a62,0x8fb1,0x9075,0x9600,0xaf80,0xc5e0,0xd034,0xd1a1,0xd551,0xd6e8,0xff6c,0xdb,0x314,0xd1c,0x4f8d,0x5bde,0x602f,0x607c,0x61a4,0x61be,0x62d6,0x654c,0x6590,0x6e10,0x6f06,0x7115,0x71d0,0x7577,0x79e9,0x7cdf,0x7f29,0x804b,0x8361,0x8471,0x848b,0x85cd,0x8680,0x8a85,0x8ce0,0x996d,0x9a97,0x9b41,0x9b8e,0xb0a9,0xb9f5,0xc878,0xc9dd,0xce7c,0xce84,0xff75,0x2e2,0x32f,0x351,0x35a,0x9b8,0xf56,0x103c,0x1ead,0x255a,0x5026,0x51a4,0x52c5,0x599d,0x5b8b,0x5c2c,0x5c34,0x5dcc,0x5e87,0x622e,0x6269,0x62a4,0x634f,0x6357,0x6b47,0x707e,0x7149,0x79a6,0x7aa6,0x7d0b,0x7e23,0x818f,0x836b,0x852d,0x88e4,0x8f5f,0x8fe6,0x903c,0x90bb,0x914c,0x91cb,0x93d1,0x9709,0x9918,0x9df2,0xb0ab,0xb155,0xb7ac,0xbb18,0xbb54,0xc12c,0xc219,0xc22b,0xc4f4,0xc549,0xcdb0,0x16e,0xd15,0xd26,0x1d49,0x2299,0x4e98,0x54c4,0x55bb,0x57b8,0x5ae9,0x5c60,0x5e9a,0x5f29,0x6028,0x6251,0x62d0,0x6372,0x647a,0x6666,0x6688,0x68c9,0x72c0,0x78b1,0x7d72,0x830e,0x8aed,0x8afe,0x8fa3,0x900a,0x9614,0x9881,0x9a91,0x9acc,0x9c39,0xbe5b,0xc9e7,0xceec,0xd0a5,0xd0d0,0xff88,0x13c,0x30f,0x36d,0xc17,0xd38,0xf61,0x266c,0x4ea9,0x4ff5,0x5446,0x54a3,0x5509,0x5f08,0x6524,0x6953,0x6bc0,0x731f,0x7aba,0x7ea4,0x7f13,0x7f79,0x7ff0,0x8070,0x8188,0x85e9,0x896f,0x8b10,0x8cf4,0x9189,0x94a7,0xb179,0xb2f7,0xbabd,0xc1e0,0xc5b9,0xc950,0x178,0x318,0x332,0xc32,0xd28,0xd4b,0xf51,0x2169,0x255d,0x4ecd,0x530d,0x5362,0x53bf,0x5582,0x55c5,0x59ec,0x5a20,0x5e1c,0x66f0,0x69a8,0x6c9f,0x6cfc,0x6e1d,0x7562,0x78b3,0x7be4,0x7ee9,0x7eea,0x8651,0x8813,0x8ced,0x8d3a,0x97fb,0x9a82,0xb8e1,0xb8e9,0xbc34,0xd6cc,0xd718,0x31a,0x101e,0x1d4d,0x2005,0x4f3d,0x55e8,0x567a,0x56e7,0x57a2,0x5bb0,0x5c27,0x61b2,0x65a5,0x668c,0x68ef,0x6977,0x6deb,0x80a4,0x8278,0x82de,0x8a60,0x8bde,0x9e21,0xae54,0xae5d,0xbb36,0xc3e0,0xc820,0xcc2e,0xcf08,0xd018,0xd0d3,0xd2c8,0xff03,0xff69,0xff94,0x9e,0x158,0x356,0xf42,0x1038,0x535c,0x53c9,0x54fc,0x5760,0x5bd3,0x5d74,0x5eb6,0x601c,0x60e7,0x615f,0x62ee,0x6321,0x66c7,0x68df,0x6912,0x6f15,0x73bb,0x755c,0x7a4f,0x7dcb,0x7ff3,0x82df,0x8749,0x8a03,0x8e87,0x987d,0x9a84,0xace7,0xb369,0xb73b,0xb9d1,0xbc0c,0xbe45,0xd15d,0xd31f,0xd514,0xff5a,0xff8d,0x137,0x162,0x30b,0x368,0x489,0xc24,0xc46,0x1d57,0x25a3,0x3231,0x4ec7,0x4f83,0x4ff1,0x5310,0x5321,0x537f,0x540f,0x5538,0x576a,0x5ab3,0x6124,0x629b,0x631a,0x66fc,0x6762,0x6adf,0x6b78,0x6bef,0x6c55,0x6f38,0x7529,0x7554,0x7587,0x7b79,0x80da,0x8be0,0x8c79,0x8d56,0x8e44,0x94c5,0x97f5,0x9e45,0x9e78,0xad1c,0xaf08,0xb2a6,0xb96d,0xc154,0xc789,0xc83c,0xca4c,0xce69,0xd188,0xff74,0xfffc,0x86,0x2d0,0x2e1,0x336,0x36a,0x710,0x7a8,0xd24,0xd35,0x1018,0x1d47,0x2044,0x5072,0x50ad,0x5270,0x54b1,0x5506,0x5564,0x5586,0x55a7,0x5c91,0x5c9a,0x646f,0x6631,0x664b,0x66fd,0x67da,0x681e,0x6a61,0x6bb4,0x6bc5,0x6c1b,0x6c4e,0x6c81,0x6cc4,0x72f1,0x745f,0x7ce7,0x81fc,0x853d,0x859b,0x8a63,0x8e8a,0x92f3,0x950b,0x96bc,0x96ef,0x97ee,0x9ce9,0xb800,0xbed7,0xc0f7,0xc2ed,0xc881,0xc8c4,0xcbe4,0xcf69,0xcfe8,0xd3a0,0xfe,0x164,0x1e3,0x252,0x2da,0x337,0x6d5,0x788,0x906,0x90f,0x917,0xd36,0x10d4,0x10dd,0x1a18,0x1e47,0x1eb5,0x226e,0x24e2,0x2584,0x262e,0x2669,0x30c5,0x4f30,0x4faf,0x52f8,0x5480,0x55b1,0x5925,0x5a25,0x5ec2,0x6346,0x64ab,0x655e,0x65cc,0x67ca,0x689f,0x6962,0x6984,0x6b50,0x6ba4,0x6d01,0x6eaa,0x76c3,0x7a63,0x7f77,0x803b,0x8098,0x8205,0x8403,0x8494,0x86cd,0x887f,0x8beb,0x8c6b,0x8f1b,0x947c,0x9756,0x99ed,0x9cf3,0x9d95,0xac9f,0xad04,0xaebe,0xaecf,0xb0b3,0xb1cc,0xb81b,0xb834,0xbd05,0xbed0,0xbf50,0xcc4c,0xd058,0xd234,0xd751,0x9a,0x12a,0x35b,0x363,0x679,0x9cb,0x10d5,0x12a0,0x226f,0x2464,0x51ea,0x5632,0x563b,0x5687,0x598d,0x5bbe,0x5df7,0x5f5d,0x5fa8,0x6064,0x622f,0x64ac,0x64c5,0x64e7,0x6e34,0x6eab,0x6fa1,0x715c,0x727d,0x7483,0x7898,0x7ebd,0x817f,0x87c4,0x8877,0x8a07,0x8d2f,0x9012,0x9081,0x9089,0x947d,0x984e,0x9870,0x991a,0x99ff,0x9ebf,0x9f61,0xb3cb,0xb4ec,0xb989,0xba67,0xbc43,0xc5fd,0xd3ab,0xfc61,0x1d4,0x218,0x22a,0x254,0x298,0x306,0x328,0x364,0x92b,0xd85,0xdaf,0xdc0,0xe0d,0x102d,0x1a01,0x1e63,0x2465,0x309e,0x4e5e,0x4f2a,0x4f43,0x503a,0x51d1,0x528d,0x53e0,0x56ee,0x5bd0,0x5d2d,0x5d57,0x61d2,0x64fa,0x687f,0x6de8,0x6e13,0x745a,0x78d4,0x7b06,0x7c6c,0x8317,0x8331,0x8427,0x849f,0x84d1,0x8559,0x85ea,0x8d9f,0x8e59,0x91ab,0x9530,0x9a5f,0x9baa,0xacb9,0xace4,0xb355,0xb380, 62 | 0xb784,0xbc11,0xbe75,0xc65c,0xc77d,0xc78e,0xc7a6,0xcea0,0xd3b4,0xfc62,0xff67,0x2bb,0x33b,0x343,0x35d,0x365,0x6c7,0x6e9,0x71d,0x9bc,0x9cd,0xdb8,0xe4a,0x121b,0x129b,0x17b6,0x1ea7,0x1edb,0x2312,0x2466,0x318d,0x4ea2,0x5351,0x54d7,0x553e,0x56a2,0x56bc,0x59ca,0x5c62,0x5d14,0x67a2,0x67ab,0x6c1f,0x6dc7,0x6e83,0x7119,0x745b,0x75ae,0x75d8,0x7845,0x7919,0x7955,0x7aaa,0x7b5d,0x7f14,0x7f94,0x83b1,0x83b9,0x83ba,0x854a,0x85af,0x8c10,0x8cdc,0x8e74,0x9072,0x971e,0x9748,0x9bab,0x9f4a,0xacaa,0xb10c,0xbbac,0xbcbc,0xc12f,0xc3df,0xc5ff,0xc6dc,0xcff5,0xd790,0xfba7,0xff68,0xff79,0xff8b,0xff9c,0x14,0x124,0x28a,0x300,0x319,0x32b,0x6c8,0x902,0xdba,0x1004,0x102f,0x10e1,0x122d,0x1466,0x1a14,0x1eb1,0x2261,0x4fd5,0x4fde,0x4fef,0x5055,0x56b4,0x5a07,0x5c38,0x5e25,0x5e61,0x5ee0,0x60bc,0x6191,0x61ff,0x6636,0x6735,0x6900,0x69c3,0x69cc,0x6a44,0x6a80,0x6d85,0x6d8e,0x72ee,0x73c2,0x747e,0x75e2,0x76d0,0x7901,0x795f,0x7a92,0x7b19,0x7bdd,0x7cfe,0x7d06,0x7d17,0x7d3a,0x7eda,0x7fe9,0x80be,0x80fa,0x813e,0x8270,0x85c9,0x87f2,0x8b8a,0x8d29,0x8d4c,0x8d54,0x8d5d,0x8da8,0x8f85,0x96c9,0x9a7b,0x9aa4,0x9b4f,0x9bd6,0x9cc4,0xac81,0xae65,0xb258,0xb313,0xb371,0xb6b1,0xb764,0xb959,0xb9d8,0xba84,0xc0f4,0xc4f8,0xc96c,0xcc14,0xcf55,0xd0ed,0xd131,0x20b,0x309,0x30a,0x31b,0x345,0x947,0x9ad,0xdc3,0xe10,0x10d9,0x144e,0x14c4,0x1a15,0x2729,0x27a0,0x30fe,0x4e3f,0x4fce,0x4fdf,0x5023,0x51f6,0x5243,0x52fe,0x53db,0x5449,0x545b,0x54d1,0x563f,0x5ba0,0x5deb,0x5df3,0x5e15,0x5f7b,0x5fb5,0x60b4,0x6233,0x626f,0x634c,0x64d2,0x6538,0x65b7,0x6615,0x6824,0x699b,0x6cd3,0x6d53,0x758f,0x76fc,0x7825,0x78fa,0x7a46,0x7e31,0x7e8f,0x7f38,0x7ffc,0x80bf,0x819d,0x82c5,0x8309,0x84b2,0x84bb,0x865c,0x8a36,0x8b02,0x8d5e,0x8fc1,0x9508,0x95bb,0x985b,0x9b03,0x9b25,0x9be8,0x9ec3,0x9f90,0xac13,0xb729,0xb985,0xbfcc,0xc2fc,0xc571,0xcfc4,0xd47c,0xfffb,0x283,0x401,0x7a7,0x948,0x995,0x9bf,0xbbe,0x1a05,0x261b,0x2708,0x503e,0x5208,0x5428,0x5527,0x5ec8,0x5eda,0x5ee2,0x6014,0x618b,0x6289,0x63bb,0x6410,0x6454,0x6740,0x68fa,0x6ccc,0x722d,0x7378,0x757f,0x778e,0x7815,0x80c0,0x8173,0x8393,0x85a9,0x85e5,0x88d9,0x88f3,0x8904,0x8c1c,0x8c93,0x8d1b,0x8f90,0x8fc2,0x9017,0x9215,0x94f8,0x96cc,0xafd4,0xb2eb,0xb755,0xba64,0xca54,0xcad3,0xce94,0xcf13,0xd14d,0xfb01,0xfc5e,0xff85,0x347,0x790,0x9af,0xb95,0xd82,0xdac,0xdbd,0x1403,0x1450,0x1483,0x1a17,0x52b3,0x55fd,0x5641,0x568e,0x5e42,0x6084,0x60b6,0x60e9,0x60fb,0x6194,0x62ac,0x6491,0x66c9,0x6da1,0x6eba,0x6ee4,0x6f31,0x7027,0x70eb,0x712f,0x71fb,0x733e,0x737a,0x75a1,0x77b0,0x78da,0x79bf,0x7a84,0x7e4d,0x7eee,0x8086,0x8273,0x8482,0x8523,0x8c50,0x8e5f,0x8fe5,0x903b,0x9175,0x925b,0x94be,0x96de,0x98a0,0x9ab0,0x9df9,0xb044,0xb091,0xb154,0xb1a8,0xb374,0xb451,0xb72c,0xc232,0xc80a,0xd0b4,0xd321,0xfb02,0xfc5f,0xff6d,0x30d,0x31e,0x326,0x340,0x362,0x36b,0x780,0x7aa,0xa97,0xab0,0xac1,0xb38,0xbaf,0x1000,0x101a,0x1781,0x1fd6,0x2012,0x215e,0x2199,0x21bb,0x2265,0x24d1,0x2504,0x4e53,0x4f6c,0x4fda,0x5147,0x5323,0x5367,0x5378,0x53a2,0x5499,0x5587,0x55d3,0x56c9,0x56ca,0x5bf0,0x5d6f,0x5f6d,0x6063,0x62d7,0x6324,0x633e,0x63ac,0x6401,0x6478,0x6500,0x65a1,0x665d,0x67ec,0x6805,0x6816,0x69c7,0x6b1d,0x6bd7,0x6c13,0x6ca3,0x6e44,0x6ed4,0x6f32,0x6fb9,0x70c1,0x70db,0x7116,0x71fc,0x72e1,0x731d,0x737b,0x7435,0x748b,0x75bc,0x75d5,0x762b,0x777f,0x77a0,0x78ca,0x7aaf,0x7cd7,0x7d68,0x7d9c,0x7ef7,0x7f1a,0x7f9a,0x807f,0x8087,0x80e4,0x810f,0x82eb,0x841d,0x8700,0x8766,0x8854,0x8a6d,0x8d25,0x8f67,0x8f70,0x8f8a,0x949e,0x94a5,0x968b,0x96bd,0x9701,0x981a,0x9877,0x9921,0x9ad3,0x9aed,0x9bc9,0x9e3f,0xb0c4,0xb188,0xb2a0,0xb540,0xb69d,0xb82c,0xc068,0xc464,0xc574,0xc6e1,0xc70c,0xc7ad,0xcac4,0xcbd4,0xd399,0xf8eb,0xf9d0,0xff6e,0x25c,0x27e,0x30e,0x316,0x31f,0x330,0x349,0x36c,0x6ce,0x6f8,0x712,0x723,0x92a,0x943,0xa2a,0xb06,0xb4b,0xd37,0xf7a,0x1ea5,0x20a3,0x2211,0x222b,0x2329,0x24d2,0x261e,0x270c,0x3094,0x4e54,0x4ed3,0x50d1,0x5151,0x5195,0x543d,0x5478,0x5580,0x55d4,0x56e4,0x5d1b,0x5e99,0x5f10,0x61c8,0x6361,0x637b,0x65f7,0x6655,0x6930,0x69d9,0x6c61,0x6c72,0x6c83,0x6c8c,0x6cbe,0x6d9c,0x6e0a,0x6e23,0x6f33,0x6f4d,0x7076,0x707f,0x73ae,0x7436,0x754f,0x75a3,0x76ef,0x775e,0x77aa,0x78cb,0x7cae,0x7eac,0x7f45,0x8110,0x8198,0x81a0,0x8569,0x856a,0x86ce,0x870a,0x8734,0x874e,0x8778,0x8822,0x892a,0x8ab9,0x8b17,0x8bdb,0x8c41,0x8c6c,0x8d1e,0x8d6b,0x90a2,0x9119,0x9320,0x937e,0x9713,0x9a4d,0x9a6f,0x9a9a,0x9ba8,0x9cb8,0xac31,0xacc1,0xb2ff,0xb428,0xba78,0xbaab,0xc553,0xc597,0xce75,0xcf85,0xcffc,0xd2f8,0xff91,0x12,0xde,0x1ff,0x317,0x320,0x331,0x33a,0x34b,0x353,0x463,0x4b7,0x4d9,0x56b,0x672,0x6a4,0x6c6,0x78b,0x7ac,0xab2,0xb32,0xbcb,0xd16,0xea5,0x101c,0x12aa,0x1e5b,0x1ed9,0x1eeb,0x2160,0x21a3,0x2517,0x25b8,0x25ca,0x321c,0x4e19,0x4fa8,0x4ffe,0x542d,0x5435,0x54ce,0x54df,0x5556,0x5608,0x5a1f,0x5a74,0x5b8d,0x5cad,0x5ce8,0x6252,0x639e,0x6634,0x665f,0x68f5,0x6b05,0x6bd9,0x6c2f,0x6cfb,0x6e3e,0x701a,0x70c3,0x71f5,0x7239,0x72fd,0x73d1,0x7624,0x7792,0x79b1,0x7aed,0x7bb8,0x7c27,0x7f24,0x8180,0x81e5,0x8218,0x8881,0x8aee,0x8bf5,0x8c17,0x8d16,0x8f0c,0x8f61,0x9497,0x9505,0x96b6,0x9945,0x9ae6,0x9b4d,0x9c3b,0x9e9f,0xad75,0xb0ad,0xb531,0xb72f,0xb968,0xc0d0,0xc370,0xc378,0xc53b,0xc587,0xc606,0xc639,0xc653,0xc705,0xc796,0xca0c,0xcf20,0xd0b7,0xd5dd,0xd720,0x123,0x145,0x21a,0x2dd,0x307,0x321,0x329,0x32a,0x398,0x3cb,0x4a7,0x4e3,0xa2c,0xa70,0xb4d,0xb9a,0xbb2,0xf0d,0x102e,0x1036,0x1ec1,0x2202,0x2260,0x25e4,0x270e,0x4e56,0x5018,0x5021,0x502a,0x50f5,0x515c,0x527d,0x547b,0x54fa,0x55bd,0x5ae3,0x5b6c,0x5ba6,0x5ce1,0x5d69,0x5ed6,0x5f1b,0x60ee,0x63b7,0x64bf,0x64d8,0x6572,0x673d,0x6789,0x6e8c,0x6f13,0x7078,0x71ee,0x7526,0x7c7e,0x7d63,0x7e5a,0x7e8d,0x8109,0x8112,0x82bb,0x8343,0x8725,0x889c,0x8956,0x8a1b,0x8bff,0x8d31,0x8d4b,0x8fe9,0x90b5,0x9171,0x918b,0x970d,0x9773,0x9971,0x9b4e,0x9d3b,0x9e64,0x9edb,0xac1a,0xad90,0xae5c,0xb125,0xb381,0xb3d5,0xb480,0xb6f4,0xb738,0xc11e,0xc313,0xc580,0xc607,0xc698,0xc90d,0xc9c7,0xcd09,0xd0c9,0xd48b,0xd6a1,0x281,0x333,0x34d,0x355,0x35e,0x366,0x4ba,0x57e,0x784,0x78d,0x7ae,0x9df,0xa1c,0xa3e,0xa9c,0xca1,0xd21,0xea7,0xf41,0xf63,0x1235,0x179f,0x1eb9,0x2283,0x4e82,0x4edf,0x50e5,0x516e,0x51cb,0x51ed,0x5220,0x53fc,0x54a5,0x5594,0x55b5,0x5657,0x58cc,0x5c41,0x5c49,0x5cd9,0x5f0b,0x5f57,0x60d5,0x613c,0x62c2,0x6342,0x638f,0x6405,0x6452,0x6867,0x68cd,0x6955,0x6a2b,0x6abb,0x6da6,0x6dda,0x6e26,0x6ef2,0x70ac,0x70bd,0x7464,0x7574,0x760d,0x7ade,0x7b3c,0x7c43,0x7cdc,0x7eb7,0x7f9e,0x803f,0x80f1,0x82cd,0x8429,0x8490,0x856d,0x8993,0x8c19,0x8caa,0x8e39,0x8e42,0x94ee,0x95b1,0x96c1,0x96db,0x98ea,0x9f4b,0xac12,0xb18d,0xb86c,0xba48,0xbc0b,0xbe80,0xc0ec,0xc369,0xc501,0xc570,0xc6dd,0xc9d9,0xcad9,0xcef7,0xd230,0xd30d,0xd54f,0xfffa,0x13f,0x312,0x323,0x334,0x33d,0x367,0x4a1,0x7a6,0x936,0xaa4,0xab5,0xb2d,0xb3e,0x1797,0x17d2,0x1ffe,0x2215,0x2570,0x2611,0x26a1,0x276e,0x4ec6,0x4fa3,0x5188,0x5191,0x51bb,0x524c,0x527f,0x5364,0x557c,0x5636,0x5713,0x5955,0x59dd,0x5c39,0x5de2,0x5f14,0x60ac,0x60f0,0x61ab,0x6200,0x62cc,0x632a,0x640f,0x6417,0x64ec,0x64fd,0x698a,0x6bb2,0x6cf5,0x6da7,0x6db8,0x6e5b,0x6ee2,0x6f62,0x70f9,0x71ac,0x7490,0x75d2,0x7737,0x776b,0x7784,0x77e9,0x7ad6,0x7caa,0x7e6d,0x7edb,0x7ee3,0x8026,0x817b,0x81c6,0x8235,0x82ac,0x835f,0x8a1d,0x8a25,0x8bbd,0x8c0a,0x8c23,0x8d2b,0x8d3c,0x907d,0x92c6,0x9489,0x949b,0x96fe,0x9739,0x9838,0x98af,0x98da,0x98e2,0x9c57,0x9d09,0x9f7f,0xb141,0xb545,0xb5bc,0xb611,0xb98e,0xbafc,0xbf08,0xbfd4,0xc274,0xc37c,0xc384,0xc557,0xc6cd,0xccc7,0xcef8,0xcf67,0xcf70,0xf02d,0xfb44,0x8e,0x115,0x261,0x31c,0x32d,0x335,0x33e,0x54d,0x56f,0x6b1,0x6cb,0x6d3,0x720,0x786,0x7b0,0x9ae,0xa40,0xb3f,0xbb5,0xd23,0xeb2,0x1006,0x1017,0x10d2,0x10db,0x126b,0x1798,0x17c2,0x1ecd,0x1fe5,0x2117,0x25ac,0x2601,0x276f,0x3099,0x4e1e,0x4fad,0x5291,0x532a,0x53ed,0x54fd,0x562f,0x594e,0x5978,0x5ae6,0x5baa,0x5c7f,0x5f2f,0x5fd0,0x61ac,0x621b,0x6292,0x635e,0x63a9,0x63f6,0x642a,0x65a7,0x6715,0x68ad,0x68b5,0x68e0,0x6b67,0x6b89,0x6e17,0x7194,0x71d7,0x72f8,0x732c,0x73de,0x743c,0x75b9,0x75c2,0x787c,0x78e1,0x78f2,0x79be,0x7a14,0x7a9d,0x7afa,0x7bb4,0x7cd5,0x7d33,0x7eb1,0x7f75,0x82ad,0x831c,0x83c5,0x851a,0x8599,0x8654,0x8717,0x8852,0x8a6b,0x8c2d,0x8d0a,0x8d2c,0x8d81,0x8e99,0x90b8,0x9149,0x9163,0x9295,0x94f0,0x95ef,0x9611,0x9688,0x9798,0x97a0,0x9897,0x98f4,0x9952,0x9985,0x9b51,0x9e70,0x9e92,0xac94,0xb51c,0xb6ab,0xb810,0xc385,0xc583,0xc660,0xc6f0,0xd5d0,0xd6d7,0xe035,0xfbde,0xff96,0x6,0x325,0x32e,0x33f,0x358,0x38c,0x5bc,0x69a,0x718,0x721,0x729,0x72a,0x787,0x905,0x916,0x985,0x9c0,0xaaf,0xac0,0xb15,0xd2d,0xf55,0xf66,0x120e,0x12eb,0x179a,0x1ebd,0x2000,0x2008,0x2198,0x2228,0x263e,0x4e1f,0x4e52,0x4fae,0x4fb6,0x50b5,0x51bd,0x51d6,0x51e7,0x524e,0x5289,0x5319,0x53ee,0x5443,0x57ae,0x592d,0x5993,0x5b5f,0x5d4c,0x5dba,0x5f27,0x5fd1,0x606b,0x61fa,0x62df,0x63c4,0x652a,0x6727,0x67d1,0x67e2,0x693f,0x6b93,0x6bdf,0x6c9b,0x6cde,0x70af,0x70d9,0x72e0,0x72f9,0x7360,0x7368,0x74f7,0x766e,0x7690,0x76b1,0x76ba,0x7852,0x7940,0x7d0a,0x7f87,0x7fa8,0x814a,0x852c,0x863c,0x87ba,0x88f4,0x8ba5,0x8bb6,0x8e81,0x94b5,0x9890,0x9a6d,0x9a7e,0x9a8f,0x9aa7,0x9ab8,0x9ad2,0x9ae3,0x9af4,0x9c48,0x9ed6,0x9f2c,0xaf2c,0xaf34,0xb080,0xb220,0xb550,0xb69c,0xbc1f,0xd329 63 | } 64 | ); 65 | 66 | size_t try_utf8_char_step(const unsigned char* buffer, size_t buffer_size, long offset); 67 | 68 | int get_language_group(wchar_t c); 69 | 70 | extracted_string* try_extract_string(const unsigned char* buffer, size_t buffer_size, long offset, size_t min_chars); 71 | 72 | std::tuple, bool> try_extract_string_tuple(const unsigned char* buffer, size_t buffer_size, long offset, size_t min_chars, bool only_interesting); 73 | 74 | vector, bool>> extract_all_strings(const unsigned char buffer[], size_t buffer_size, size_t min_chars, bool only_interesting); 75 | -------------------------------------------------------------------------------- /strings/dirent.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* 4 | * Dirent interface for Microsoft Visual Studio 5 | * Version 1.21 6 | * 7 | * Copyright (C) 2006-2012 Toni Ronkko 8 | * This file is part of dirent. Dirent may be freely distributed 9 | * under the MIT license. For all details and documentation, see 10 | * https://github.com/tronkko/dirent 11 | */ 12 | #ifndef DIRENT_H 13 | #define DIRENT_H 14 | 15 | /* 16 | * Include windows.h without Windows Sockets 1.1 to prevent conflicts with 17 | * Windows Sockets 2.0. 18 | */ 19 | #ifndef WIN32_LEAN_AND_MEAN 20 | # define WIN32_LEAN_AND_MEAN 21 | #endif 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | /* Indicates that d_type field is available in dirent structure */ 35 | #define _DIRENT_HAVE_D_TYPE 36 | 37 | /* Indicates that d_namlen field is available in dirent structure */ 38 | #define _DIRENT_HAVE_D_NAMLEN 39 | 40 | /* Entries missing from MSVC 6.0 */ 41 | #if !defined(FILE_ATTRIBUTE_DEVICE) 42 | # define FILE_ATTRIBUTE_DEVICE 0x40 43 | #endif 44 | 45 | /* File type and permission flags for stat(), general mask */ 46 | #if !defined(S_IFMT) 47 | # define S_IFMT _S_IFMT 48 | #endif 49 | 50 | /* Directory bit */ 51 | #if !defined(S_IFDIR) 52 | # define S_IFDIR _S_IFDIR 53 | #endif 54 | 55 | /* Character device bit */ 56 | #if !defined(S_IFCHR) 57 | # define S_IFCHR _S_IFCHR 58 | #endif 59 | 60 | /* Pipe bit */ 61 | #if !defined(S_IFFIFO) 62 | # define S_IFFIFO _S_IFFIFO 63 | #endif 64 | 65 | /* Regular file bit */ 66 | #if !defined(S_IFREG) 67 | # define S_IFREG _S_IFREG 68 | #endif 69 | 70 | /* Read permission */ 71 | #if !defined(S_IREAD) 72 | # define S_IREAD _S_IREAD 73 | #endif 74 | 75 | /* Write permission */ 76 | #if !defined(S_IWRITE) 77 | # define S_IWRITE _S_IWRITE 78 | #endif 79 | 80 | /* Execute permission */ 81 | #if !defined(S_IEXEC) 82 | # define S_IEXEC _S_IEXEC 83 | #endif 84 | 85 | /* Pipe */ 86 | #if !defined(S_IFIFO) 87 | # define S_IFIFO _S_IFIFO 88 | #endif 89 | 90 | /* Block device */ 91 | #if !defined(S_IFBLK) 92 | # define S_IFBLK 0 93 | #endif 94 | 95 | /* Link */ 96 | #if !defined(S_IFLNK) 97 | # define S_IFLNK 0 98 | #endif 99 | 100 | /* Socket */ 101 | #if !defined(S_IFSOCK) 102 | # define S_IFSOCK 0 103 | #endif 104 | 105 | /* Read user permission */ 106 | #if !defined(S_IRUSR) 107 | # define S_IRUSR S_IREAD 108 | #endif 109 | 110 | /* Write user permission */ 111 | #if !defined(S_IWUSR) 112 | # define S_IWUSR S_IWRITE 113 | #endif 114 | 115 | /* Execute user permission */ 116 | #if !defined(S_IXUSR) 117 | # define S_IXUSR 0 118 | #endif 119 | 120 | /* Read group permission */ 121 | #if !defined(S_IRGRP) 122 | # define S_IRGRP 0 123 | #endif 124 | 125 | /* Write group permission */ 126 | #if !defined(S_IWGRP) 127 | # define S_IWGRP 0 128 | #endif 129 | 130 | /* Execute group permission */ 131 | #if !defined(S_IXGRP) 132 | # define S_IXGRP 0 133 | #endif 134 | 135 | /* Read others permission */ 136 | #if !defined(S_IROTH) 137 | # define S_IROTH 0 138 | #endif 139 | 140 | /* Write others permission */ 141 | #if !defined(S_IWOTH) 142 | # define S_IWOTH 0 143 | #endif 144 | 145 | /* Execute others permission */ 146 | #if !defined(S_IXOTH) 147 | # define S_IXOTH 0 148 | #endif 149 | 150 | /* Maximum length of file name */ 151 | #if !defined(PATH_MAX) 152 | # define PATH_MAX MAX_PATH 153 | #endif 154 | #if !defined(FILENAME_MAX) 155 | # define FILENAME_MAX MAX_PATH 156 | #endif 157 | #if !defined(NAME_MAX) 158 | # define NAME_MAX FILENAME_MAX 159 | #endif 160 | 161 | /* File type flags for d_type */ 162 | #define DT_UNKNOWN 0 163 | #define DT_REG S_IFREG 164 | #define DT_DIR S_IFDIR 165 | #define DT_FIFO S_IFIFO 166 | #define DT_SOCK S_IFSOCK 167 | #define DT_CHR S_IFCHR 168 | #define DT_BLK S_IFBLK 169 | #define DT_LNK S_IFLNK 170 | 171 | /* Macros for converting between st_mode and d_type */ 172 | #define IFTODT(mode) ((mode) & S_IFMT) 173 | #define DTTOIF(type) (type) 174 | 175 | /* 176 | * File type macros. Note that block devices, sockets and links cannot be 177 | * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are 178 | * only defined for compatibility. These macros should always return false 179 | * on Windows. 180 | */ 181 | #if !defined(S_ISFIFO) 182 | # define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) 183 | #endif 184 | #if !defined(S_ISDIR) 185 | # define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) 186 | #endif 187 | #if !defined(S_ISREG) 188 | # define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) 189 | #endif 190 | #if !defined(S_ISLNK) 191 | # define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) 192 | #endif 193 | #if !defined(S_ISSOCK) 194 | # define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) 195 | #endif 196 | #if !defined(S_ISCHR) 197 | # define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) 198 | #endif 199 | #if !defined(S_ISBLK) 200 | # define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) 201 | #endif 202 | 203 | /* Return the exact length of d_namlen without zero terminator */ 204 | #define _D_EXACT_NAMLEN(p) ((p)->d_namlen) 205 | 206 | /* Return number of bytes needed to store d_namlen */ 207 | #define _D_ALLOC_NAMLEN(p) (PATH_MAX) 208 | 209 | 210 | #ifdef __cplusplus 211 | extern "C" { 212 | #endif 213 | 214 | 215 | /* Wide-character version */ 216 | struct _wdirent { 217 | /* Always zero */ 218 | long d_ino; 219 | 220 | /* Structure size */ 221 | unsigned short d_reclen; 222 | 223 | /* Length of name without \0 */ 224 | size_t d_namlen; 225 | 226 | /* File type */ 227 | int d_type; 228 | 229 | /* File name */ 230 | wchar_t d_name[PATH_MAX]; 231 | }; 232 | typedef struct _wdirent _wdirent; 233 | 234 | struct _WDIR { 235 | /* Current directory entry */ 236 | struct _wdirent ent; 237 | 238 | /* Private file data */ 239 | WIN32_FIND_DATAW data; 240 | 241 | /* True if data is valid */ 242 | int cached; 243 | 244 | /* Win32 search handle */ 245 | HANDLE handle; 246 | 247 | /* Initial directory name */ 248 | wchar_t *patt; 249 | }; 250 | typedef struct _WDIR _WDIR; 251 | 252 | static _WDIR *_wopendir(const wchar_t *dirname); 253 | static struct _wdirent *_wreaddir(_WDIR *dirp); 254 | static int _wclosedir(_WDIR *dirp); 255 | static void _wrewinddir(_WDIR* dirp); 256 | 257 | 258 | /* For compatibility with Symbian */ 259 | #define wdirent _wdirent 260 | #define WDIR _WDIR 261 | #define wopendir _wopendir 262 | #define wreaddir _wreaddir 263 | #define wclosedir _wclosedir 264 | #define wrewinddir _wrewinddir 265 | 266 | 267 | /* Multi-byte character versions */ 268 | struct dirent { 269 | /* Always zero */ 270 | long d_ino; 271 | 272 | /* Structure size */ 273 | unsigned short d_reclen; 274 | 275 | /* Length of name without \0 */ 276 | size_t d_namlen; 277 | 278 | /* File type */ 279 | int d_type; 280 | 281 | /* File name */ 282 | char d_name[PATH_MAX]; 283 | }; 284 | typedef struct dirent dirent; 285 | 286 | struct DIR { 287 | struct dirent ent; 288 | struct _WDIR *wdirp; 289 | }; 290 | typedef struct DIR DIR; 291 | 292 | static DIR *opendir(const char *dirname); 293 | static struct dirent *readdir(DIR *dirp); 294 | static int closedir(DIR *dirp); 295 | static void rewinddir(DIR* dirp); 296 | 297 | 298 | /* Internal utility functions */ 299 | static WIN32_FIND_DATAW *dirent_first(_WDIR *dirp); 300 | static WIN32_FIND_DATAW *dirent_next(_WDIR *dirp); 301 | 302 | static int dirent_mbstowcs_s( 303 | size_t *pReturnValue, 304 | wchar_t *wcstr, 305 | size_t sizeInWords, 306 | const char *mbstr, 307 | size_t count); 308 | 309 | static int dirent_wcstombs_s( 310 | size_t *pReturnValue, 311 | char *mbstr, 312 | size_t sizeInBytes, 313 | const wchar_t *wcstr, 314 | size_t count); 315 | 316 | static void dirent_set_errno(int error); 317 | 318 | /* 319 | * Open directory stream DIRNAME for read and return a pointer to the 320 | * internal working area that is used to retrieve individual directory 321 | * entries. 322 | */ 323 | static _WDIR* 324 | _wopendir( 325 | const wchar_t *dirname) 326 | { 327 | _WDIR *dirp = NULL; 328 | int error; 329 | 330 | /* Must have directory name */ 331 | if (dirname == NULL || dirname[0] == '\0') { 332 | dirent_set_errno(ENOENT); 333 | return NULL; 334 | } 335 | 336 | /* Allocate new _WDIR structure */ 337 | dirp = (_WDIR*)malloc(sizeof(struct _WDIR)); 338 | if (dirp != NULL) { 339 | DWORD n; 340 | 341 | /* Reset _WDIR structure */ 342 | dirp->handle = INVALID_HANDLE_VALUE; 343 | dirp->patt = NULL; 344 | dirp->cached = 0; 345 | 346 | /* Compute the length of full path plus zero terminator 347 | * 348 | * Note that on WinRT there's no way to convert relative paths 349 | * into absolute paths, so just assume its an absolute path. 350 | */ 351 | # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) 352 | n = wcslen(dirname); 353 | # else 354 | n = GetFullPathNameW(dirname, 0, NULL, NULL); 355 | # endif 356 | 357 | /* Allocate room for absolute directory name and search pattern */ 358 | dirp->patt = (wchar_t*)malloc(sizeof(wchar_t) * n + 16); 359 | if (dirp->patt) { 360 | 361 | /* 362 | * Convert relative directory name to an absolute one. This 363 | * allows rewinddir() to function correctly even when current 364 | * working directory is changed between opendir() and rewinddir(). 365 | * 366 | * Note that on WinRT there's no way to convert relative paths 367 | * into absolute paths, so just assume its an absolute path. 368 | */ 369 | # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) 370 | wcsncpy_s(dirp->patt, n + 1, dirname, n); 371 | # else 372 | n = GetFullPathNameW(dirname, n, dirp->patt, NULL); 373 | # endif 374 | if (n > 0) { 375 | wchar_t *p; 376 | 377 | /* Append search pattern \* to the directory name */ 378 | p = dirp->patt + n; 379 | if (dirp->patt < p) { 380 | switch (p[-1]) { 381 | case '\\': 382 | case '/': 383 | case ':': 384 | /* Directory ends in path separator, e.g. c:\temp\ */ 385 | /*NOP*/; 386 | break; 387 | 388 | default: 389 | /* Directory name doesn't end in path separator */ 390 | *p++ = '\\'; 391 | } 392 | } 393 | *p++ = '*'; 394 | *p = '\0'; 395 | 396 | /* Open directory stream and retrieve the first entry */ 397 | if (dirent_first(dirp)) { 398 | /* Directory stream opened successfully */ 399 | error = 0; 400 | } 401 | else { 402 | /* Cannot retrieve first entry */ 403 | error = 1; 404 | dirent_set_errno(ENOENT); 405 | } 406 | 407 | } 408 | else { 409 | /* Cannot retrieve full path name */ 410 | dirent_set_errno(ENOENT); 411 | error = 1; 412 | } 413 | 414 | } 415 | else { 416 | /* Cannot allocate memory for search pattern */ 417 | error = 1; 418 | } 419 | 420 | } 421 | else { 422 | /* Cannot allocate _WDIR structure */ 423 | error = 1; 424 | } 425 | 426 | /* Clean up in case of error */ 427 | if (error && dirp) { 428 | _wclosedir(dirp); 429 | dirp = NULL; 430 | } 431 | 432 | return dirp; 433 | } 434 | 435 | /* 436 | * Read next directory entry. The directory entry is returned in dirent 437 | * structure in the d_name field. Individual directory entries returned by 438 | * this function include regular files, sub-directories, pseudo-directories 439 | * "." and ".." as well as volume labels, hidden files and system files. 440 | */ 441 | static struct _wdirent* 442 | _wreaddir( 443 | _WDIR *dirp) 444 | { 445 | WIN32_FIND_DATAW *datap; 446 | struct _wdirent *entp; 447 | 448 | /* Read next directory entry */ 449 | datap = dirent_next(dirp); 450 | if (datap) { 451 | size_t n; 452 | DWORD attr; 453 | 454 | /* Pointer to directory entry to return */ 455 | entp = &dirp->ent; 456 | 457 | /* 458 | * Copy file name as wide-character string. If the file name is too 459 | * long to fit in to the destination buffer, then truncate file name 460 | * to PATH_MAX characters and zero-terminate the buffer. 461 | */ 462 | n = 0; 463 | while (n + 1 < PATH_MAX && datap->cFileName[n] != 0) { 464 | entp->d_name[n] = datap->cFileName[n]; 465 | n++; 466 | } 467 | dirp->ent.d_name[n] = 0; 468 | 469 | /* Length of file name excluding zero terminator */ 470 | entp->d_namlen = n; 471 | 472 | /* File type */ 473 | attr = datap->dwFileAttributes; 474 | if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { 475 | entp->d_type = DT_CHR; 476 | } 477 | else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { 478 | entp->d_type = DT_DIR; 479 | } 480 | else { 481 | entp->d_type = DT_REG; 482 | } 483 | 484 | /* Reset dummy fields */ 485 | entp->d_ino = 0; 486 | entp->d_reclen = sizeof(struct _wdirent); 487 | 488 | } 489 | else { 490 | 491 | /* Last directory entry read */ 492 | entp = NULL; 493 | 494 | } 495 | 496 | return entp; 497 | } 498 | 499 | /* 500 | * Close directory stream opened by opendir() function. This invalidates the 501 | * DIR structure as well as any directory entry read previously by 502 | * _wreaddir(). 503 | */ 504 | static int 505 | _wclosedir( 506 | _WDIR *dirp) 507 | { 508 | int ok; 509 | if (dirp) { 510 | 511 | /* Release search handle */ 512 | if (dirp->handle != INVALID_HANDLE_VALUE) { 513 | FindClose(dirp->handle); 514 | dirp->handle = INVALID_HANDLE_VALUE; 515 | } 516 | 517 | /* Release search pattern */ 518 | if (dirp->patt) { 519 | free(dirp->patt); 520 | dirp->patt = NULL; 521 | } 522 | 523 | /* Release directory structure */ 524 | free(dirp); 525 | ok = /*success*/0; 526 | 527 | } 528 | else { 529 | /* Invalid directory stream */ 530 | dirent_set_errno(EBADF); 531 | ok = /*failure*/-1; 532 | } 533 | return ok; 534 | } 535 | 536 | /* 537 | * Rewind directory stream such that _wreaddir() returns the very first 538 | * file name again. 539 | */ 540 | static void 541 | _wrewinddir( 542 | _WDIR* dirp) 543 | { 544 | if (dirp) { 545 | /* Release existing search handle */ 546 | if (dirp->handle != INVALID_HANDLE_VALUE) { 547 | FindClose(dirp->handle); 548 | } 549 | 550 | /* Open new search handle */ 551 | dirent_first(dirp); 552 | } 553 | } 554 | 555 | /* Get first directory entry (internal) */ 556 | static WIN32_FIND_DATAW* 557 | dirent_first( 558 | _WDIR *dirp) 559 | { 560 | WIN32_FIND_DATAW *datap; 561 | 562 | /* Open directory and retrieve the first entry */ 563 | dirp->handle = FindFirstFileExW( 564 | dirp->patt, FindExInfoStandard, &dirp->data, 565 | FindExSearchNameMatch, NULL, 0); 566 | if (dirp->handle != INVALID_HANDLE_VALUE) { 567 | 568 | /* a directory entry is now waiting in memory */ 569 | datap = &dirp->data; 570 | dirp->cached = 1; 571 | 572 | } 573 | else { 574 | 575 | /* Failed to re-open directory: no directory entry in memory */ 576 | dirp->cached = 0; 577 | datap = NULL; 578 | 579 | } 580 | return datap; 581 | } 582 | 583 | /* Get next directory entry (internal) */ 584 | static WIN32_FIND_DATAW* 585 | dirent_next( 586 | _WDIR *dirp) 587 | { 588 | WIN32_FIND_DATAW *p; 589 | 590 | /* Get next directory entry */ 591 | if (dirp->cached != 0) { 592 | 593 | /* A valid directory entry already in memory */ 594 | p = &dirp->data; 595 | dirp->cached = 0; 596 | 597 | } 598 | else if (dirp->handle != INVALID_HANDLE_VALUE) { 599 | 600 | /* Get the next directory entry from stream */ 601 | if (FindNextFileW(dirp->handle, &dirp->data) != FALSE) { 602 | /* Got a file */ 603 | p = &dirp->data; 604 | } 605 | else { 606 | /* The very last entry has been processed or an error occured */ 607 | FindClose(dirp->handle); 608 | dirp->handle = INVALID_HANDLE_VALUE; 609 | p = NULL; 610 | } 611 | 612 | } 613 | else { 614 | 615 | /* End of directory stream reached */ 616 | p = NULL; 617 | 618 | } 619 | 620 | return p; 621 | } 622 | 623 | /* 624 | * Open directory stream using plain old C-string. 625 | */ 626 | static DIR* 627 | opendir( 628 | const char *dirname) 629 | { 630 | struct DIR *dirp; 631 | int error; 632 | 633 | /* Must have directory name */ 634 | if (dirname == NULL || dirname[0] == '\0') { 635 | dirent_set_errno(ENOENT); 636 | return NULL; 637 | } 638 | 639 | /* Allocate memory for DIR structure */ 640 | dirp = (DIR*)malloc(sizeof(struct DIR)); 641 | if (dirp) { 642 | wchar_t wname[PATH_MAX]; 643 | size_t n; 644 | 645 | /* Convert directory name to wide-character string */ 646 | error = dirent_mbstowcs_s(&n, wname, PATH_MAX, dirname, PATH_MAX); 647 | if (!error) { 648 | 649 | /* Open directory stream using wide-character name */ 650 | dirp->wdirp = _wopendir(wname); 651 | if (dirp->wdirp) { 652 | /* Directory stream opened */ 653 | error = 0; 654 | } 655 | else { 656 | /* Failed to open directory stream */ 657 | error = 1; 658 | } 659 | 660 | } 661 | else { 662 | /* 663 | * Cannot convert file name to wide-character string. This 664 | * occurs if the string contains invalid multi-byte sequences or 665 | * the output buffer is too small to contain the resulting 666 | * string. 667 | */ 668 | error = 1; 669 | } 670 | 671 | } 672 | else { 673 | /* Cannot allocate DIR structure */ 674 | error = 1; 675 | } 676 | 677 | /* Clean up in case of error */ 678 | if (error && dirp) { 679 | free(dirp); 680 | dirp = NULL; 681 | } 682 | 683 | return dirp; 684 | } 685 | 686 | /* 687 | * Read next directory entry. 688 | * 689 | * When working with text consoles, please note that file names returned by 690 | * readdir() are represented in the default ANSI code page while any output to 691 | * console is typically formatted on another code page. Thus, non-ASCII 692 | * characters in file names will not usually display correctly on console. The 693 | * problem can be fixed in two ways: (1) change the character set of console 694 | * to 1252 using chcp utility and use Lucida Console font, or (2) use 695 | * _cprintf function when writing to console. The _cprinf() will re-encode 696 | * ANSI strings to the console code page so many non-ASCII characters will 697 | * display correcly. 698 | */ 699 | static struct dirent* 700 | readdir( 701 | DIR *dirp) 702 | { 703 | WIN32_FIND_DATAW *datap; 704 | struct dirent *entp; 705 | 706 | /* Read next directory entry */ 707 | datap = dirent_next(dirp->wdirp); 708 | if (datap) { 709 | size_t n; 710 | int error; 711 | 712 | /* Attempt to convert file name to multi-byte string */ 713 | error = dirent_wcstombs_s( 714 | &n, dirp->ent.d_name, PATH_MAX, datap->cFileName, PATH_MAX); 715 | 716 | /* 717 | * If the file name cannot be represented by a multi-byte string, 718 | * then attempt to use old 8+3 file name. This allows traditional 719 | * Unix-code to access some file names despite of unicode 720 | * characters, although file names may seem unfamiliar to the user. 721 | * 722 | * Be ware that the code below cannot come up with a short file 723 | * name unless the file system provides one. At least 724 | * VirtualBox shared folders fail to do this. 725 | */ 726 | if (error && datap->cAlternateFileName[0] != '\0') { 727 | error = dirent_wcstombs_s( 728 | &n, dirp->ent.d_name, PATH_MAX, 729 | datap->cAlternateFileName, PATH_MAX); 730 | } 731 | 732 | if (!error) { 733 | DWORD attr; 734 | 735 | /* Initialize directory entry for return */ 736 | entp = &dirp->ent; 737 | 738 | /* Length of file name excluding zero terminator */ 739 | entp->d_namlen = n - 1; 740 | 741 | /* File attributes */ 742 | attr = datap->dwFileAttributes; 743 | if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { 744 | entp->d_type = DT_CHR; 745 | } 746 | else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { 747 | entp->d_type = DT_DIR; 748 | } 749 | else { 750 | entp->d_type = DT_REG; 751 | } 752 | 753 | /* Reset dummy fields */ 754 | entp->d_ino = 0; 755 | entp->d_reclen = sizeof(struct dirent); 756 | 757 | } 758 | else { 759 | /* 760 | * Cannot convert file name to multi-byte string so construct 761 | * an errornous directory entry and return that. Note that 762 | * we cannot return NULL as that would stop the processing 763 | * of directory entries completely. 764 | */ 765 | entp = &dirp->ent; 766 | entp->d_name[0] = '?'; 767 | entp->d_name[1] = '\0'; 768 | entp->d_namlen = 1; 769 | entp->d_type = DT_UNKNOWN; 770 | entp->d_ino = 0; 771 | entp->d_reclen = 0; 772 | } 773 | 774 | } 775 | else { 776 | /* No more directory entries */ 777 | entp = NULL; 778 | } 779 | 780 | return entp; 781 | } 782 | 783 | /* 784 | * Close directory stream. 785 | */ 786 | static int 787 | closedir( 788 | DIR *dirp) 789 | { 790 | int ok; 791 | if (dirp) { 792 | 793 | /* Close wide-character directory stream */ 794 | ok = _wclosedir(dirp->wdirp); 795 | dirp->wdirp = NULL; 796 | 797 | /* Release multi-byte character version */ 798 | free(dirp); 799 | 800 | } 801 | else { 802 | 803 | /* Invalid directory stream */ 804 | dirent_set_errno(EBADF); 805 | ok = /*failure*/-1; 806 | 807 | } 808 | return ok; 809 | } 810 | 811 | /* 812 | * Rewind directory stream to beginning. 813 | */ 814 | static void 815 | rewinddir( 816 | DIR* dirp) 817 | { 818 | /* Rewind wide-character string directory stream */ 819 | _wrewinddir(dirp->wdirp); 820 | } 821 | 822 | /* Convert multi-byte string to wide character string */ 823 | static int 824 | dirent_mbstowcs_s( 825 | size_t *pReturnValue, 826 | wchar_t *wcstr, 827 | size_t sizeInWords, 828 | const char *mbstr, 829 | size_t count) 830 | { 831 | int error; 832 | 833 | #if defined(_MSC_VER) && _MSC_VER >= 1400 834 | 835 | /* Microsoft Visual Studio 2005 or later */ 836 | error = mbstowcs_s(pReturnValue, wcstr, sizeInWords, mbstr, count); 837 | 838 | #else 839 | 840 | /* Older Visual Studio or non-Microsoft compiler */ 841 | size_t n; 842 | 843 | /* Convert to wide-character string (or count characters) */ 844 | n = mbstowcs(wcstr, mbstr, sizeInWords); 845 | if (!wcstr || n < count) { 846 | 847 | /* Zero-terminate output buffer */ 848 | if (wcstr && sizeInWords) { 849 | if (n >= sizeInWords) { 850 | n = sizeInWords - 1; 851 | } 852 | wcstr[n] = 0; 853 | } 854 | 855 | /* Length of resuting multi-byte string WITH zero terminator */ 856 | if (pReturnValue) { 857 | *pReturnValue = n + 1; 858 | } 859 | 860 | /* Success */ 861 | error = 0; 862 | 863 | } 864 | else { 865 | 866 | /* Could not convert string */ 867 | error = 1; 868 | 869 | } 870 | 871 | #endif 872 | 873 | return error; 874 | } 875 | 876 | /* Convert wide-character string to multi-byte string */ 877 | static int 878 | dirent_wcstombs_s( 879 | size_t *pReturnValue, 880 | char *mbstr, 881 | size_t sizeInBytes, /* max size of mbstr */ 882 | const wchar_t *wcstr, 883 | size_t count) 884 | { 885 | int error; 886 | 887 | #if defined(_MSC_VER) && _MSC_VER >= 1400 888 | 889 | /* Microsoft Visual Studio 2005 or later */ 890 | error = wcstombs_s(pReturnValue, mbstr, sizeInBytes, wcstr, count); 891 | 892 | #else 893 | 894 | /* Older Visual Studio or non-Microsoft compiler */ 895 | size_t n; 896 | 897 | /* Convert to multi-byte string (or count the number of bytes needed) */ 898 | n = wcstombs(mbstr, wcstr, sizeInBytes); 899 | if (!mbstr || n < count) { 900 | 901 | /* Zero-terminate output buffer */ 902 | if (mbstr && sizeInBytes) { 903 | if (n >= sizeInBytes) { 904 | n = sizeInBytes - 1; 905 | } 906 | mbstr[n] = '\0'; 907 | } 908 | 909 | /* Length of resulting multi-bytes string WITH zero-terminator */ 910 | if (pReturnValue) { 911 | *pReturnValue = n + 1; 912 | } 913 | 914 | /* Success */ 915 | error = 0; 916 | 917 | } 918 | else { 919 | 920 | /* Cannot convert string */ 921 | error = 1; 922 | 923 | } 924 | 925 | #endif 926 | 927 | return error; 928 | } 929 | 930 | /* Set errno variable */ 931 | static void 932 | dirent_set_errno( 933 | int error) 934 | { 935 | #if defined(_MSC_VER) && _MSC_VER >= 1400 936 | 937 | /* Microsoft Visual Studio 2005 and later */ 938 | _set_errno(error); 939 | 940 | #else 941 | 942 | /* Non-Microsoft compiler or older Microsoft compiler */ 943 | errno = error; 944 | 945 | #endif 946 | } 947 | 948 | 949 | #ifdef __cplusplus 950 | } 951 | #endif 952 | #endif /*DIRENT_H*/ 953 | -------------------------------------------------------------------------------- /strings/extracted_string.cpp: -------------------------------------------------------------------------------- 1 | // Class for extracted strings 2 | #include "stdafx.h" 3 | #include "extracted_string.hpp" 4 | 5 | using namespace std; 6 | 7 | std::wstring_convert> _converter; 8 | 9 | extracted_string::extracted_string() 10 | { 11 | m_type = TYPE_UNDETERMINED; 12 | m_string = (std::string)NULL; 13 | m_size_in_bytes = 0; 14 | m_offset_start = 0; 15 | m_offset_end = 0; 16 | } 17 | 18 | extracted_string::extracted_string(const char* string, size_t size_in_bytes, STRING_TYPE type, int offset_start, int offset_end) 19 | { 20 | m_type = type; 21 | m_string = std::string(string, size_in_bytes); 22 | m_size_in_bytes = size_in_bytes; 23 | m_offset_start = offset_start; 24 | m_offset_end = offset_end; 25 | } 26 | 27 | extracted_string::extracted_string(const wchar_t* string, size_t size_in_bytes, STRING_TYPE type, int offset_start, int offset_end) 28 | { 29 | m_type = type; 30 | 31 | // Convert to UTF8 string 32 | m_string = _converter.to_bytes(string, string + size_in_bytes / 2); 33 | //m_string = _wchar_to_utf8(string, size_in_bytes); 34 | 35 | m_size_in_bytes = size_in_bytes; 36 | m_offset_start = offset_start; 37 | m_offset_end = offset_end; 38 | } 39 | 40 | float extracted_string::get_proba_interesting() 41 | { 42 | // Returns a probability of the string being interesting, 0.0 to 1.0. 43 | // An interesting string is non-gibberish. Gibberish is mostly erroneous 44 | // short extracted strings from binary content. 45 | 46 | // The model is trained to only support strings of length 4 to 7. Longer 47 | // strings are asssumed to be interesting, shorter assumed gibberish.. 48 | int l = m_string.length(); 49 | if (l > 16) 50 | return 1.0f; 51 | if (l < 4) 52 | return 0.0f; 53 | 54 | // Score the features 55 | // 118 character unigrams (character ranges 0x9 to 0x7e) 56 | // 118 + 118*118 character bigrams 57 | // 1 for the total number of characters in string 58 | // 1 for the total number of > 0x128 ascii code 59 | // 1 for distinct character count 60 | float score = string_model::bias; 61 | unordered_set cc; // Character counts 62 | for (size_t i = 0; i < l; i++) 63 | { 64 | // Count distinct characters 65 | cc.insert(m_string[i]); 66 | 67 | if (m_string[i] >= 0x9 && m_string[i] <= 0x7E) 68 | { 69 | // Unigram 70 | score += string_model::weights[m_string[i] - 0x9]; 71 | 72 | // Bigram 73 | if (i + 1 < l && m_string[i + 1] >= 0x9 && m_string[i + 1] <= 0x7E) 74 | { 75 | score += string_model::weights[118 + (m_string[i] - 0x9) + 118 * (m_string[i + 1] - 0x9)]; 76 | } 77 | } 78 | else 79 | { 80 | // Number of non-latin unicode characters 81 | score += string_model::weights[118 + 118 + 118 * 118 + 1]; 82 | } 83 | } 84 | 85 | // Add the string length weight 86 | score += string_model::weights[118 + 118 + 118 * 118] * (float)l; 87 | 88 | // Add the distinct character count weight 89 | score += string_model::weights[118 + 118 + 118 * 118 + 2] * (float)cc.size(); 90 | 91 | // Convert it to a probability 92 | return 1.0f / (1.0f + exp(-score)); 93 | } 94 | 95 | size_t extracted_string::get_size_in_bytes() 96 | { 97 | return m_size_in_bytes; 98 | } 99 | 100 | string extracted_string::get_string() 101 | { 102 | return m_string; 103 | } 104 | 105 | bool extracted_string::is_interesting() 106 | { 107 | return get_proba_interesting() > 0.5f; 108 | } 109 | 110 | STRING_TYPE extracted_string::get_type() 111 | { 112 | return m_type; 113 | } 114 | 115 | string extracted_string::get_type_string() 116 | { 117 | if (m_type == TYPE_UTF8) 118 | { 119 | return "UTF8"; 120 | } 121 | else if (m_type == TYPE_WIDE_STRING) 122 | { 123 | return "WIDE_STRING"; 124 | } 125 | else 126 | { 127 | return "UNDETERMINED"; 128 | } 129 | } 130 | 131 | int extracted_string::get_offset_start() 132 | { 133 | return m_offset_start; 134 | } 135 | 136 | int extracted_string::get_offset_end() 137 | { 138 | return m_offset_end; 139 | } 140 | 141 | extracted_string::~extracted_string() 142 | { 143 | // Nothing to do 144 | } -------------------------------------------------------------------------------- /strings/extracted_string.hpp: -------------------------------------------------------------------------------- 1 | // Class for extracted strings 2 | #pragma once 3 | #include 4 | #include 5 | #include "string_model.h" 6 | #include 7 | 8 | using namespace std; 9 | 10 | enum STRING_TYPE 11 | { 12 | TYPE_UNDETERMINED, 13 | TYPE_UTF8, 14 | TYPE_WIDE_STRING 15 | }; 16 | 17 | 18 | 19 | class extracted_string 20 | { 21 | private: 22 | STRING_TYPE m_type; 23 | std::string m_string; // Supports Utf8 24 | size_t m_size_in_bytes; 25 | int m_offset_start; 26 | int m_offset_end; 27 | 28 | public: 29 | extracted_string(); 30 | extracted_string(const char* string, size_t size_in_bytes, STRING_TYPE type, int offset_start, int offset_end); 31 | extracted_string(const wchar_t* string, size_t size_in_bytes, STRING_TYPE type, int offset_start, int offset_end); 32 | 33 | float get_proba_interesting(); 34 | size_t get_size_in_bytes(); 35 | string get_string(); 36 | STRING_TYPE get_type(); 37 | string get_type_string(); 38 | int get_offset_start(); 39 | int get_offset_end(); 40 | 41 | bool is_interesting(); 42 | 43 | ~extracted_string(); 44 | }; 45 | -------------------------------------------------------------------------------- /strings/memory_strings.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "memory_strings.h" 3 | 4 | bool IsWin64(HANDLE process) 5 | { 6 | BOOL ret_val; 7 | if( IsWow64Process(process, &ret_val) ) 8 | { 9 | return ret_val; 10 | } 11 | PrintLastError((LPTSTR) L"IsWow64Process"); 12 | return false; 13 | } 14 | 15 | bool memory_strings::dump_system() 16 | { 17 | // Enumerate processes, and process the strings from each one 18 | HANDLE h_snapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); 19 | 20 | if( h_snapshot != INVALID_HANDLE_VALUE ) 21 | { 22 | // Handle the first i_process 23 | PROCESSENTRY32 tmp_p; 24 | tmp_p.dwSize = sizeof(PROCESSENTRY32); 25 | int result; 26 | if( (result = Process32First(h_snapshot, &tmp_p)) ) 27 | { 28 | if( result == TRUE ) 29 | dump_process(tmp_p.th32ProcessID); 30 | 31 | while( (result = Process32Next(h_snapshot, &tmp_p)) ) 32 | { 33 | if( result == TRUE ) 34 | dump_process(tmp_p.th32ProcessID); 35 | } 36 | } 37 | 38 | // Cleanup the handle 39 | CloseHandle( h_snapshot ); 40 | return true; 41 | } 42 | return false; 43 | } 44 | 45 | bool memory_strings::dump_process(DWORD pid) 46 | { 47 | // Open the process 48 | HANDLE ph = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pid); 49 | if( ph != NULL ) 50 | { 51 | // Assign the process name 52 | char process_name[0x100] = { 0 }; 53 | GetModuleBaseNameA(ph, 0, process_name, 0x100 ); 54 | 55 | // Generate memory region list 56 | HANDLE hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid); 57 | if ( hSnapshot != INVALID_HANDLE_VALUE ) 58 | { 59 | this->_generate_module_list(hSnapshot); 60 | CloseHandle(hSnapshot); 61 | 62 | // Walk through the process regions, extracting the strings 63 | bool result = this->_process_all_memory(ph, process_name); 64 | 65 | return result; 66 | }else{ 67 | fprintf(stderr,"Failed gather module information for process 0x%x (%i). ", pid, pid); 68 | PrintLastError( (LPTSTR) L"dump_process"); 69 | } 70 | }else{ 71 | fprintf(stderr,"Failed open process 0x%x (%i). ", pid, pid); 72 | PrintLastError((LPTSTR) L"dump_process"); 73 | } 74 | return false; 75 | } 76 | 77 | memory_strings::memory_strings(string_parser* parser) 78 | { 79 | this->m_parser = parser; 80 | } 81 | 82 | 83 | MBI_BASIC_INFO memory_strings::_get_mbi_info(unsigned __int64 address, HANDLE ph) 84 | { 85 | _MEMORY_BASIC_INFORMATION64 mbi; 86 | MBI_BASIC_INFO result; 87 | result.base = 0; 88 | result.end = 0; 89 | result.protect = 0; 90 | result.valid = false; 91 | result.executable = false; 92 | 93 | // Load this heap information 94 | __int64 blockSize = VirtualQueryEx(ph, (LPCVOID)address, (PMEMORY_BASIC_INFORMATION)&mbi, sizeof(_MEMORY_BASIC_INFORMATION64)); 95 | 96 | if (blockSize == sizeof(_MEMORY_BASIC_INFORMATION64)) 97 | { 98 | result.base = mbi.BaseAddress; 99 | result.end = mbi.BaseAddress + mbi.RegionSize; 100 | result.protect = mbi.Protect; 101 | result.valid = mbi.State != MEM_FREE && !(mbi.Protect & (PAGE_NOACCESS | PAGE_GUARD)); 102 | result.executable = (mbi.Protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)) > 0; 103 | result.size = mbi.RegionSize; 104 | } 105 | else if (blockSize == sizeof(_MEMORY_BASIC_INFORMATION32)) 106 | { 107 | _MEMORY_BASIC_INFORMATION32* mbi32 = (_MEMORY_BASIC_INFORMATION32*)&mbi; 108 | 109 | result.base = mbi32->BaseAddress; 110 | result.end = (long long) mbi32->BaseAddress + (long long)mbi32->RegionSize; 111 | result.protect = mbi32->Protect; 112 | result.valid = mbi32->State != MEM_FREE && !(mbi32->Protect & (PAGE_NOACCESS | PAGE_GUARD)); 113 | result.executable = (mbi32->Protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)) > 0; 114 | result.size = mbi.RegionSize; 115 | } 116 | 117 | return result; 118 | } 119 | 120 | bool memory_strings::_process_all_memory(HANDLE ph, string process_name) 121 | { 122 | // Set the max address of the target process. Assume it is a 64 bit process. 123 | unsigned __int64 max_address = 0xffffffffffffffff; // Not a problem for 32bit targets 124 | 125 | // Walk the process heaps 126 | unsigned __int64 address = 0; 127 | 128 | while (address < max_address) 129 | { 130 | // Load this region information 131 | MBI_BASIC_INFO mbi_info = _get_mbi_info(address, ph); 132 | 133 | if (mbi_info.end + 1 <= address) 134 | break; 135 | address = mbi_info.end + 1; 136 | 137 | if(mbi_info.valid && mbi_info.size > 0) 138 | { 139 | // Process this region 140 | 141 | // Read in the region 142 | unsigned char* buffer = new unsigned char[mbi_info.size]; 143 | if( buffer != NULL ) 144 | { 145 | unsigned __int64 num_read = 0; 146 | bool result = ReadProcessMemory(ph, (LPCVOID) mbi_info.base, buffer, mbi_info.size,(SIZE_T*) &num_read); 147 | 148 | //fprintf(stderr,"Current address: %016llX\n",mbi.BaseAddress); 149 | if( num_read > 0 ) 150 | { 151 | if( num_read != mbi_info.size) 152 | fprintf(stderr,"Failed read full region from address 0x%llx: %s. Only %lld of expected %lld bytes were read.\n", mbi_info.base, strerror(errno), num_read, mbi_info.size); 153 | 154 | // Load the module name if applicable 155 | string module_name_short = "region"; 156 | string module_name_long = "region"; 157 | 158 | for (int i = 0; i < m_modules.size(); i++) 159 | { 160 | if (m_modules[i].contains((PVOID64) mbi_info.base)) 161 | { 162 | module_name_short = m_modules[i].get_filename(); 163 | module_name_long = m_modules[i].get_filepath(); 164 | } 165 | } 166 | 167 | // Print the strings from this region 168 | std::stringstream long_name; 169 | long_name << process_name << ":" << module_name_long << "@0x" << std::hex << mbi_info.base; 170 | std::stringstream short_name; 171 | short_name << process_name << ":" << module_name_short << "@0x" << std::hex << mbi_info.base; 172 | m_parser->parse_block( buffer, num_read, short_name.str(), long_name.str(), mbi_info.base ); 173 | } 174 | 175 | // Cleanup 176 | delete[] buffer; 177 | }else{ 178 | fprintf(stderr,"Failed to allocate space of %lld for reading in a region.", mbi_info.size); 179 | } 180 | } 181 | } 182 | 183 | return true; 184 | } 185 | 186 | void memory_strings::_generate_module_list(HANDLE hSnapshot) 187 | { 188 | MODULEENTRY32 tmp_m; 189 | tmp_m.dwSize = sizeof(MODULEENTRY32); 190 | if( Module32First(hSnapshot, &tmp_m) ) 191 | { 192 | // Add this i_module to our array 193 | tmp_m.dwSize = sizeof(MODULEENTRY32); 194 | m_modules.push_back(module(tmp_m)); 195 | 196 | while(Module32Next(hSnapshot,&tmp_m)) 197 | { 198 | // Add this i_module to our array 199 | m_modules.push_back(module(tmp_m)); 200 | tmp_m.dwSize = sizeof(MODULEENTRY32); 201 | } 202 | } 203 | } 204 | 205 | memory_strings::~memory_strings(void) 206 | { 207 | } 208 | -------------------------------------------------------------------------------- /strings/memory_strings.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "windows.h" 3 | #include "module.h" 4 | #include 5 | #include "string_parser.h" 6 | #include 7 | #include 8 | #include "basics.h" 9 | #include 10 | #include 11 | 12 | #pragma comment(lib, "Psapi") 13 | using namespace std; 14 | 15 | struct MBI_BASIC_INFO 16 | { 17 | unsigned __int64 base; 18 | unsigned __int64 end; 19 | DWORD protect; 20 | bool valid; 21 | bool executable; 22 | unsigned __int64 size; 23 | }; 24 | 25 | class memory_strings 26 | { 27 | vector m_modules; 28 | string_parser* m_parser; 29 | 30 | void _generate_module_list(HANDLE hSnapshot); 31 | bool _process_all_memory(HANDLE ph, string process_name); 32 | MBI_BASIC_INFO _get_mbi_info(unsigned __int64 address, HANDLE ph); 33 | public: 34 | memory_strings(string_parser* parser); 35 | bool dump_process(DWORD pid); 36 | bool dump_system(); 37 | 38 | ~memory_strings(void); 39 | }; 40 | -------------------------------------------------------------------------------- /strings/module.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "module.h" 3 | 4 | bool module::contains(PVOID64 address) 5 | { 6 | // Check if this module contains the specified address 7 | return (BYTE*) address >= m_module_details.modBaseAddr && (BYTE*) address < m_module_details.modBaseAddr + m_module_details.modBaseSize; 8 | } 9 | 10 | string module::get_filepath() 11 | { 12 | wstring ws = m_module_details.szExePath; 13 | 14 | using convert_type = std::codecvt_utf8; 15 | std::wstring_convert converter; 16 | 17 | //use converter (.to_bytes: wstr->str, .from_bytes: str->wstr) 18 | return converter.to_bytes(ws); 19 | } 20 | 21 | string module::get_filename() 22 | { 23 | wstring ws = m_module_details.szModule; 24 | 25 | using convert_type = std::codecvt_utf8; 26 | std::wstring_convert converter; 27 | 28 | //use converter (.to_bytes: wstr->str, .from_bytes: str->wstr) 29 | return converter.to_bytes(ws); 30 | } 31 | 32 | bool module::operator== (const module &other) const 33 | { 34 | return this->m_module_details.hModule == other.m_module_details.hModule; 35 | } 36 | 37 | module::module(MODULEENTRY32W details) 38 | { 39 | m_module_details = details; 40 | } 41 | 42 | module::~module(void) 43 | { 44 | } 45 | -------------------------------------------------------------------------------- /strings/module.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | class module 12 | { 13 | MODULEENTRY32W m_module_details; 14 | public: 15 | bool contains(PVOID64 address); 16 | string get_filepath(); 17 | string get_filename(); 18 | 19 | module(MODULEENTRY32W details); 20 | ~module(void); 21 | bool operator== (const module &other) const; 22 | }; 23 | -------------------------------------------------------------------------------- /strings/print_buffer.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "print_buffer.h" 3 | #include 4 | 5 | print_buffer::print_buffer(int buffer_size) 6 | { 7 | this->m_buffer_size = buffer_size; 8 | this->m_buffer = new char[buffer_size]; 9 | this->m_space_used = 0; 10 | } 11 | 12 | void print_buffer::add_string(const char* string, size_t length) 13 | { 14 | // Digest the buffer if it is full 15 | if( m_space_used + length + 1 >= m_buffer_size ) 16 | digest(); 17 | 18 | // Copy the string if there is room 19 | if( m_space_used + length + 1 >= m_buffer_size ) 20 | { 21 | // Digest this string without buffering it 22 | fwrite(string, length, 1, stdout); 23 | }else{ 24 | // Add it to the buffer 25 | memcpy( m_buffer + m_space_used, string, length ); 26 | m_space_used += length; 27 | m_buffer[m_space_used] = 0; 28 | } 29 | } 30 | 31 | void print_buffer::add_string(const char* string) 32 | { 33 | int length = strlen(string); 34 | add_string(string, length); 35 | } 36 | 37 | void print_buffer::add_string(string string) 38 | { 39 | add_string(string.c_str(), string.length()); 40 | } 41 | 42 | void print_buffer::add_json_string(string json) 43 | { 44 | // Json string building is formed as an array of json objects. 45 | // We prepend "[" at the first log, comma delmit, then post-fix a "]" upon completion. 46 | if (m_is_start) 47 | { 48 | add_string("[" + json); 49 | m_is_start = false; 50 | m_add_json_close = true; 51 | } 52 | else 53 | { 54 | add_string("," + json); 55 | } 56 | } 57 | 58 | void print_buffer::digest() 59 | { 60 | if( m_space_used > 0 ) 61 | { 62 | // Print the current buffer 63 | fwrite( m_buffer, 1, m_space_used, stdout); 64 | fflush( stdout ); 65 | m_buffer[0] = 0; 66 | m_space_used = 0; 67 | } 68 | } 69 | 70 | print_buffer::~print_buffer(void) 71 | { 72 | if (m_add_json_close) 73 | add_string("]"); 74 | digest(); 75 | delete[] m_buffer; 76 | 77 | 78 | } 79 | -------------------------------------------------------------------------------- /strings/print_buffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | class print_buffer 9 | { 10 | bool m_is_start = true; 11 | bool m_add_json_close = false; 12 | int m_buffer_size; 13 | int m_space_used; 14 | char* m_buffer; 15 | public: 16 | void add_string(const char* string, size_t length); 17 | void add_string(const char* string); 18 | void add_string(string string); 19 | 20 | void add_json_string(string json); 21 | 22 | void digest(); 23 | print_buffer(int buffer_size); 24 | ~print_buffer(void); 25 | }; 26 | -------------------------------------------------------------------------------- /strings/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by strings.rc 4 | 5 | // Next default values for new objects 6 | // 7 | #ifdef APSTUDIO_INVOKED 8 | #ifndef APSTUDIO_READONLY_SYMBOLS 9 | #define _APS_NEXT_RESOURCE_VALUE 101 10 | #define _APS_NEXT_COMMAND_VALUE 40001 11 | #define _APS_NEXT_CONTROL_VALUE 1001 12 | #define _APS_NEXT_SYMED_VALUE 101 13 | #endif 14 | #endif 15 | -------------------------------------------------------------------------------- /strings/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // strings.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /strings/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #include 11 | #include 12 | 13 | 14 | 15 | // TODO: reference additional headers your program requires here 16 | -------------------------------------------------------------------------------- /strings/string_parser.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "string_parser.h" 3 | 4 | using namespace nlohmann; 5 | 6 | bool string_parser::parse_block(unsigned char* buffer, unsigned int buffer_length, string name_short, string name_long, unsigned long long base_address) 7 | { 8 | if( buffer != NULL && buffer_length > 0) 9 | { 10 | // Process this buffer 11 | vector, bool>> r_vect = extract_all_strings(buffer, buffer_length, this->m_options.min_chars, !this->m_options.print_not_interesting); 12 | 13 | 14 | if (m_options.print_json) 15 | { 16 | // Output the strings to a json file 17 | json j; 18 | j["name_short"] = name_short; 19 | j["name_long"] = name_long; 20 | for (int i = 0; i < r_vect.size(); i++) 21 | { 22 | j["strings"][i]["string"] = std::get<0>(r_vect[i]); 23 | j["strings"][i]["type"] = std::get<1>(r_vect[i]); 24 | j["strings"][i]["span"] = { std::get<2>(r_vect[i]).first + base_address, std::get<2>(r_vect[i]).second + base_address }; 25 | j["strings"][i]["is_interesting"] = std::get<3>(r_vect[i]); 26 | } 27 | this->m_printer->add_json_string(j.dump()); 28 | } 29 | else 30 | { 31 | // Iterate through the resulting strings, printing them 32 | for (int i = 0; i < r_vect.size(); i++) 33 | { 34 | bool is_interesting = std::get<3>(r_vect[i]); 35 | if (is_interesting && m_options.print_interesting || 36 | !is_interesting && m_options.print_not_interesting) 37 | { 38 | // Add the prefixes as appropriate 39 | if (m_options.print_filepath) 40 | this->m_printer->add_string(name_long + ","); 41 | 42 | if (m_options.print_filename) 43 | this->m_printer->add_string(name_short + ","); 44 | 45 | if (m_options.print_string_type) 46 | this->m_printer->add_string(std::get<1>(r_vect[i]) + ","); 47 | 48 | if (m_options.print_span) 49 | { 50 | std::stringstream span; 51 | span << std::hex << "(0x" << (std::get<2>(r_vect[i]).first + base_address) << ",0x" << (std::get<2>(r_vect[i]).second + base_address) << "),"; 52 | this->m_printer->add_string(span.str()); 53 | } 54 | 55 | string s = std::get<0>(r_vect[i]); 56 | if (m_options.escape_new_lines) 57 | { 58 | size_t index = 0; 59 | while (true) { 60 | /* Locate the substring to replace. */ 61 | index = s.find("\n", index); 62 | if (index == std::string::npos) break; 63 | 64 | /* Make the replacement. */ 65 | s.replace(index, 1, "\\n"); 66 | 67 | /* Advance index forward so the next iteration doesn't pick it up as well. */ 68 | index += 2; 69 | } 70 | 71 | index = 0; 72 | while (true) { 73 | /* Locate the substring to replace. */ 74 | index = s.find("\r", index); 75 | if (index == std::string::npos) break; 76 | 77 | /* Make the replacement. */ 78 | s.replace(index, 1, "\\r"); 79 | 80 | /* Advance index forward so the next iteration doesn't pick it up as well. */ 81 | index += 2; 82 | } 83 | } 84 | 85 | this->m_printer->add_string(s + "\n"); 86 | } 87 | } 88 | } 89 | } 90 | return false; 91 | } 92 | 93 | string_parser::string_parser(STRING_OPTIONS options) 94 | { 95 | m_printer = new print_buffer(0x100000); 96 | this->m_options = options; 97 | } 98 | 99 | bool string_parser::parse_stream(FILE* fh, string name_short, string name_long) 100 | { 101 | if( fh != NULL ) 102 | { 103 | unsigned char* buffer; 104 | int num_read; 105 | long long offset = 0; 106 | 107 | // Adjust the start offset if specified 108 | if (m_options.offset_start > 0) 109 | fseek(fh, m_options.offset_start, SEEK_SET); 110 | 111 | // Allocate the buffer 112 | buffer = new unsigned char[BLOCK_SIZE]; 113 | 114 | do 115 | { 116 | // Read the stream in blocks of 0x50000, assuming that a string does not border the regions. 117 | if (m_options.offset_end > 0) 118 | { 119 | num_read = fread(buffer, 1, min(BLOCK_SIZE, m_options.offset_end - m_options.offset_start), fh); 120 | } 121 | else 122 | { 123 | num_read = fread(buffer, 1, BLOCK_SIZE, fh); 124 | } 125 | 126 | 127 | if( num_read > 0 ) 128 | { 129 | // We have read in the full contents now, lets process it. 130 | if( offset > 0 ) 131 | this->parse_block( buffer, num_read, name_short, name_long + ":offset=" + to_string(offset), 0); 132 | else 133 | this->parse_block(buffer, num_read, name_short, name_long, 0); 134 | 135 | offset += num_read; 136 | } 137 | 138 | this->m_printer->digest(); 139 | }while( num_read == BLOCK_SIZE ); 140 | 141 | // Clean up 142 | delete[] buffer; 143 | return true; 144 | }else{ 145 | // Failed to open file 146 | fprintf(stderr,"Invalid stream: %s.\n", strerror(errno)); 147 | return false; 148 | } 149 | } 150 | 151 | string_parser::~string_parser(void) 152 | { 153 | delete m_printer; 154 | } 155 | -------------------------------------------------------------------------------- /strings/string_parser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "windows.h" 4 | #include "print_buffer.h" 5 | #include "binary2strings.hpp" 6 | #include "json.hpp" 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | constexpr auto MAX_STRING_SIZE = 0x2000; 13 | constexpr auto BLOCK_SIZE = 5e+7; // 50MB 14 | 15 | struct STRING_OPTIONS 16 | { 17 | bool print_utf8 = true; 18 | bool print_wide_string = true; 19 | bool print_string_type = false; 20 | bool print_interesting = true; 21 | bool print_not_interesting = false; 22 | bool print_filename = false; 23 | bool print_filepath = false; 24 | bool print_span = false; 25 | bool print_json = false; 26 | bool escape_new_lines = false; 27 | int min_chars = 4; 28 | size_t offset_start = 0; 29 | size_t offset_end = 0; 30 | }; 31 | 32 | class string_parser 33 | { 34 | // Maybe add XOR methods for extracting strings? 35 | enum EXTRACT_TYPE 36 | { 37 | EXTRACT_RAW, 38 | EXTRACT_ASM 39 | }; 40 | 41 | enum STRING_TYPE 42 | { 43 | TYPE_UNDETERMINED, 44 | TYPE_ASCII, 45 | TYPE_UNICODE 46 | }; 47 | 48 | STRING_OPTIONS m_options; 49 | print_buffer* m_printer; 50 | 51 | public: 52 | string_parser( STRING_OPTIONS options ); 53 | bool parse_block( unsigned char* buffer, unsigned int buffer_length, string name_short, string name_long, unsigned long long base_address); 54 | bool parse_stream( FILE* fh, string name_short, string name_long); 55 | ~string_parser(void); 56 | }; -------------------------------------------------------------------------------- /strings/strings.cpp: -------------------------------------------------------------------------------- 1 | // strings.cpp : Defines the entry point for the console application. 2 | // 3 | #pragma once 4 | #pragma execution_character_set( "utf-8" ) 5 | 6 | #include "stdafx.h" 7 | #include "string_parser.h" 8 | #include "windows.h" 9 | #include 10 | #include "dirent.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "Shlwapi.h" 16 | #include 17 | #include 18 | #include 19 | #include "memory_strings.h" 20 | #include 21 | #include 22 | #define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING 23 | #include 24 | 25 | 26 | using namespace std; 27 | //using namespace std::filesystem; 28 | 29 | BOOL is_win64() 30 | { 31 | #if defined(_WIN64) 32 | return TRUE; // 64-bit programs run only on Win64 33 | #elif defined(_WIN32) 34 | // 32-bit programs run on both 32-bit and 64-bit Windows 35 | // so must sniff 36 | BOOL f64 = FALSE; 37 | return IsWow64Process(GetCurrentProcess(), &f64) && f64; 38 | #else 39 | return FALSE; // Win64 does not support Win16 40 | #endif 41 | } 42 | 43 | bool is_elevated(HANDLE h_Process) 44 | { 45 | HANDLE h_Token; 46 | TOKEN_ELEVATION t_TokenElevation; 47 | TOKEN_ELEVATION_TYPE e_ElevationType; 48 | DWORD dw_TokenLength; 49 | 50 | if( OpenProcessToken(h_Process, TOKEN_READ | TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES , &h_Token) ) 51 | { 52 | if(GetTokenInformation(h_Token,TokenElevation,&t_TokenElevation,sizeof(t_TokenElevation),&dw_TokenLength)) 53 | { 54 | if(t_TokenElevation.TokenIsElevated != 0) 55 | { 56 | if(GetTokenInformation(h_Token,TokenElevationType,&e_ElevationType,sizeof(e_ElevationType),&dw_TokenLength)) 57 | { 58 | if(e_ElevationType == TokenElevationTypeFull || e_ElevationType == TokenElevationTypeDefault) 59 | { 60 | return true; 61 | } 62 | } 63 | } 64 | } 65 | } 66 | 67 | return false; 68 | } 69 | 70 | void process_folder( string dir_name, string filter, bool recursively, string_parser* parser ) 71 | { 72 | DIR *dir; 73 | struct dirent *ent; 74 | dir = opendir (dir_name.c_str()); 75 | if (dir != NULL) 76 | { 77 | /* print all the files and directories within directory */ 78 | while ((ent = readdir (dir)) != NULL) { 79 | // Convert the path to wchar format 80 | char* result = new char[ent->d_namlen + 1]; 81 | 82 | if( result != NULL ) 83 | { 84 | for( int i = 0; i < ent->d_namlen; i++ ) 85 | result[i] = ent->d_name[i]; 86 | result[ent->d_namlen] = 0; 87 | 88 | if( (ent->d_type & DT_DIR) ) 89 | { 90 | // Process this subdirectory if recursive flag is on 91 | if( recursively && strcmp(result, ".") != 0 && strcmp(result, "..") != 0 ) 92 | { 93 | // Build the directory path 94 | string next_directory = dir_name + "/" + string(ent->d_name); 95 | process_folder( next_directory, filter, recursively, parser ); 96 | } 97 | }else{ 98 | // Check if this filename is a match to the specified pattern 99 | if( PathMatchSpecA( result, filter.c_str() ) ) 100 | { 101 | // Process this file 102 | string filepath = dir_name + "/" + string(result); 103 | 104 | // Processes the specified file for strings 105 | FILE* fh = fopen( filepath.c_str(), "rb" ); 106 | if( fh != NULL ) 107 | { 108 | parser->parse_stream(fh, string(result), filepath); 109 | fclose(fh); 110 | }else{ 111 | // Error 112 | fprintf(stderr, "Error opening file %s: %s.\n", filepath.c_str(), strerror(errno)); 113 | } 114 | } 115 | } 116 | delete[] result; 117 | } 118 | else 119 | { 120 | fprintf(stderr, "Failed to allocate memory block of size %lld for filename: %s.\n", ent->d_namlen + 1, strerror(errno)); 121 | } 122 | } 123 | closedir (dir); 124 | }else{ 125 | fprintf(stderr, "Unable to open directory %s: %s.\n", dir_name.c_str(), strerror(errno)); 126 | } 127 | } 128 | 129 | 130 | bool get_privileges(HANDLE h_Process) 131 | { 132 | HANDLE h_Token; 133 | DWORD dw_TokenLength; 134 | if( OpenProcessToken(h_Process, TOKEN_READ | TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES , &h_Token) ) 135 | { 136 | // Read the old token privileges 137 | TOKEN_PRIVILEGES* privilages = new TOKEN_PRIVILEGES[100]; 138 | if( GetTokenInformation(h_Token, TokenPrivileges, privilages,sizeof(TOKEN_PRIVILEGES)*100,&dw_TokenLength) ) 139 | { 140 | // Enable all privileges 141 | for( int i = 0; i < privilages->PrivilegeCount; i++ ) 142 | { 143 | privilages->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED; 144 | } 145 | 146 | // Adjust the privilges 147 | if(AdjustTokenPrivileges( h_Token, false, privilages, sizeof(TOKEN_PRIVILEGES)*100, NULL, NULL )) 148 | { 149 | delete[] privilages; 150 | return true; 151 | } 152 | } 153 | delete[] privilages; 154 | } 155 | return false; 156 | } 157 | 158 | int _tmain(int argc, _TCHAR* argv[]) 159 | { 160 | // Enable UTF-8 console 161 | SetConsoleOutputCP(65001); 162 | 163 | // Process the flags 164 | STRING_OPTIONS options; 165 | 166 | WCHAR* filter = NULL; 167 | 168 | bool flag_help = false; 169 | bool piped_input = !_isatty( _fileno( stdin ) ); 170 | bool flag_dump_pid = false; 171 | bool flag_dump_system = false; 172 | bool flag_recursive = false; 173 | 174 | 175 | if( argc <= 1 && !piped_input ) 176 | flag_help = true; 177 | for( int i = 1; i < argc; i++ ) 178 | { 179 | if (lstrcmp(argv[i], L"--help") == 0 || lstrcmp(argv[i], L"-help") == 0 || lstrcmp(argv[i], L"-h") == 0 || lstrcmp(argv[i], L"--h") == 0) 180 | flag_help = true; 181 | else if (lstrcmp(argv[i], L"-f") == 0) 182 | options.print_filename = true; 183 | else if (lstrcmp(argv[i], L"-F") == 0) 184 | options.print_filepath = true; 185 | else if (lstrcmp(argv[i], L"-r") == 0) 186 | flag_recursive = true; 187 | else if (lstrcmp(argv[i], L"-t") == 0) 188 | options.print_string_type = true; 189 | else if (lstrcmp(argv[i], L"-s") == 0) 190 | options.print_span = true; 191 | else if (lstrcmp(argv[i], L"-e") == 0) 192 | options.escape_new_lines = true; 193 | else if (lstrcmp(argv[i], L"-json") == 0) 194 | { 195 | options.print_json = true; 196 | } 197 | else if (lstrcmp(argv[i], L"-a") == 0) 198 | { 199 | // Both all strings. Interesting and not interesting 200 | options.print_interesting = true; 201 | options.print_not_interesting = true; 202 | } 203 | else if (lstrcmp(argv[i], L"-ni") == 0) 204 | { 205 | // Only not interesting 206 | options.print_interesting = false; 207 | options.print_not_interesting = true; 208 | } 209 | else if (lstrcmp(argv[i], L"-utf") == 0 || lstrcmp(argv[i], L"-utf8") == 0) 210 | { 211 | options.print_utf8 = true; 212 | options.print_wide_string = false; 213 | } 214 | else if (lstrcmp(argv[i], L"-w") == 0 || lstrcmp(argv[i], L"-wide") == 0) 215 | { 216 | options.print_utf8 = false; 217 | options.print_wide_string = true; 218 | } 219 | else if( lstrcmp(argv[i],L"-pid") == 0 ) 220 | flag_dump_pid = true; 221 | else if( lstrcmp(argv[i],L"-system") == 0 ) 222 | flag_dump_system = true; 223 | else if (lstrcmp(argv[i], L"-b") == 0) 224 | { 225 | if (i + 1 < argc) 226 | { 227 | // Try to parse the byte range 'start(:end)' 228 | size_t start = 0; 229 | size_t end = 0; 230 | std::wstringstream sst(argv[i + 1]); 231 | if (!(sst >> start)) 232 | { 233 | fprintf(stderr, "Failed to parse -b argument start. It should be followed by a single or pair of numbers:\n\teg. 'strings2 *.exe -b 6:106'\n"); 234 | exit(0); 235 | } 236 | 237 | if (!sst.eof()) 238 | { 239 | if (sst.get() == ':') 240 | { 241 | if (!(sst >> end)) 242 | { 243 | fprintf(stderr, "Failed to parse -b argument end. It should be followed by a single or pair of numbers:\n\teg. 'strings2 *.exe -b 6:106'\n"); 244 | exit(0); 245 | } 246 | if (!sst.eof()) 247 | { 248 | fprintf(stderr, "Failed to parse -b argument expected end of options after end. It should be followed by a single or pair of numbers:\n\teg. 'strings2 *.exe -b 6:106'\n"); 249 | exit(0); 250 | } 251 | } 252 | else 253 | { 254 | fprintf(stderr, "Failed to parse -b argument expected end of options after start. It should be followed by a single or pair of numbers:\n\teg. 'strings2 *.exe -b 6:106'\n"); 255 | exit(0); 256 | } 257 | } 258 | 259 | if ( end > 0 && end < start ) 260 | { 261 | fprintf(stderr, "Failed to parse -b argument expected due to invalid specified range. It should be followed by a single or pair of numbers:\n\teg. 'strings2 *.exe -b 6:106'\n"); 262 | exit(0); 263 | } 264 | 265 | options.offset_start = start; 266 | options.offset_end = end; 267 | i++; 268 | } 269 | else 270 | { 271 | fprintf(stderr, "Failed to parse -b argument missing start and end. It should be followed by a single or pair of numbers:\n\teg. 'strings2 *.exe -b 6:106'\n"); 272 | exit(0); 273 | } 274 | } 275 | else if( lstrcmp(argv[i],L"-l") == 0 ) 276 | { 277 | if( i + 1 < argc ) 278 | { 279 | // Try to parse the number of characters 280 | int result = _wtoi(argv[i+1]); 281 | if( result >= 3 ) 282 | { 283 | options.min_chars = result; 284 | }else{ 285 | fprintf(stderr,"Failed to parse -l argument. The string size must be 3 or larger:\n\teg. 'strings2 *.exe -l 6'\n"); 286 | exit(0); 287 | } 288 | i++; 289 | }else{ 290 | fprintf(stderr,"Failed to parse -l argument. It must be followed by a number:\n\teg. 'strings2 *.exe -l 6'\n"); 291 | exit(0); 292 | } 293 | }else{ 294 | // This is an unassigned argument 295 | if( filter == NULL ) 296 | { 297 | filter = argv[i]; 298 | } 299 | else 300 | { 301 | // This argument is an error, we already found our filter. 302 | fprintf(stderr,"Failed to parse argument number %i, '%S'. Try 'strings2 --help' for usage instructions.\n", i, argv[i]); 303 | exit(0); 304 | } 305 | } 306 | } 307 | 308 | if( flag_help ) 309 | { 310 | // Print help page 311 | printf("Strings2 extracts all unicode/ascii strings from binary data. On top of the classical strings approach, this version decodes multilingual strings (eg Chinese, Russian, etc) and uses a ML model to suppress noisy uninteresting strings.\n\n"); 312 | printf("Example Usage:\n"); 313 | printf("\tstrings2 malware.exe\n"); 314 | printf("\tstrings2 *.exe > strings.txt\n"); 315 | printf("\tstrings2 ./files/*.exe > strings.txt\n"); 316 | printf("\tstrings2 -pid 419 > process_strings.txt\n"); 317 | printf("\tstrings2 -f -s -pid 0x1a3 > process_strings.txt\n"); 318 | printf("\tstrings2 -system > all_process_strings.txt\n"); 319 | printf("\ttype abcd.exe | strings2 > out.txt\n\n"); 320 | printf("\ttype abcd.exe | strings2 | findstr /i SearchForThisString\n\n"); 321 | printf("\tstrings2 malware.exe -json > strings.json\n"); 322 | printf("Flags:\n"); 323 | printf(" -r\n\tRecursively process subdirectories.\n"); 324 | printf(" -f\n\tPrints the filename/processname for each string.\n"); 325 | printf(" -F\n\tPrints the full path and filename for each string.\n"); 326 | printf(" -s\n\tPrints the file offset or memory address span\n\tof each string.\n"); 327 | printf(" -t\n\tPrints the string type for each string. UTF8,\n\tor WIDE_STRING.\n"); 328 | printf(" -wide\n\tPrints only WIDE_STRING strings that are encoded\n\tas two bytes per character.\n"); 329 | printf(" -utf\n\tPrints only UTF8 encoded strings.\n"); 330 | printf(" -a\n\tPrints both interesting and not interesting strings.\n\tDefault only prints interesting non-junk strings.\n"); 331 | printf(" -ni\n\tPrints only not interesting strings. Default only\n\tprints interesting non-junk strings.\n"); 332 | printf(" -e\n\tEscape new line characters.\n"); 333 | printf(" -l [numchars]\n\tMinimum number of characters that is a valid string.\n\tDefault is 4.\n"); 334 | printf(" -b [start](:[end])\n\tScan only the specified byte range for strings.\n"); 335 | printf(" -pid [pid]\n\tThe strings from the process address space for the\n\tspecified PID will be dumped. Use a '0x' prefix to\n\tspecify a hex PID.\n"); 336 | printf(" -system\n\tDumps strings from all accessible processes on the\n\tsystem. This takes awhile.\n"); 337 | printf(" -json\n\tWrites output as json. Many flags are ignored in this mode.\n"); 338 | }else{ 339 | // Create the string parser object 340 | string_parser* parser = new string_parser(options); 341 | 342 | if (flag_dump_pid || flag_dump_system) 343 | { 344 | // Warn if running in 32 bit mode on a 64 bit OS 345 | if( is_win64() && sizeof(void*) == 4 ) 346 | { 347 | fprintf(stderr, "WARNING: To properly dump address spaces of 64-bit processes the 64-bit version of strings2 should be used. Currently strings2 has been detected as running as a 32bit process under a 64bit operating system.\n\n"); 348 | } 349 | 350 | // Elevate strings2 to the maximum privilges 351 | get_privileges( GetCurrentProcess() ); 352 | 353 | // Create a process string dump class 354 | memory_strings* process = new memory_strings(parser); 355 | 356 | if( flag_dump_pid ) 357 | { 358 | // Extract all strings from the specified process 359 | if( filter != NULL ) 360 | { 361 | // Check the prefix 362 | bool is_hex = false; 363 | wchar_t* prefix = new wchar_t[3]; 364 | memcpy(prefix, filter, 4); 365 | prefix[2] = 0; 366 | 367 | if( wcscmp(prefix, L"0x") == 0 ) 368 | { 369 | filter = &filter[2]; 370 | is_hex = true; 371 | } 372 | delete[] prefix; 373 | 374 | // Extract the pid from the string 375 | unsigned int pid; 376 | if( (is_hex && swscanf(filter, L"%x", &pid) > 0) || 377 | (!is_hex && swscanf(filter, L"%i", &pid) > 0)) 378 | { 379 | // Successfully parsed the PID 380 | 381 | // Parse the process 382 | process->dump_process(pid); 383 | }else{ 384 | fwprintf(stderr, L"Failed to parse filter argument as a valid PID: %s.\n", filter); 385 | } 386 | }else{ 387 | fwprintf(stderr, L"Error. No PID was specified. Example usage:\n\tstrings2 -pid 419 > process_strings.txt\n"); 388 | } 389 | }else if( flag_dump_system ) 390 | { 391 | // Extract strings from the whole system 392 | process->dump_system(); 393 | } 394 | 395 | delete process; 396 | }else if (piped_input) 397 | { 398 | // Set "stdin" to have binary mode: 399 | int result = _setmode( _fileno( stdin ), _O_BINARY ); 400 | if( result == -1 ) 401 | fprintf(stderr, "Failed to set piped data mode to binary but will continue with processing of piped data." ); 402 | 403 | FILE* fh = fdopen(fileno(stdin), "rb"); 404 | 405 | if( fh != NULL ) 406 | { 407 | // Process the piped input 408 | parser->parse_stream(fh, "piped data", "piped data"); 409 | fclose(fh); 410 | }else{ 411 | // Error 412 | fprintf(stderr, "Invalid stream. Error opening the piped input: %s.\n", strerror(errno)); 413 | } 414 | }else if(filter != NULL) 415 | { 416 | // Convert filter to string 417 | std::wstring ws = filter; 418 | std::string f(ws.begin(), ws.end()); 419 | 420 | // Split the filter into the directory and filename filter halves 421 | filesystem::path p(f); 422 | 423 | if( p.has_filename() || p.has_parent_path() ) 424 | { 425 | // Process the specified files 426 | string parent_path = "."; 427 | if (p.has_parent_path()) 428 | parent_path = p.parent_path().string(); 429 | 430 | string filename = "*"; 431 | if (p.has_filename()) 432 | filename = p.filename().string(); 433 | 434 | process_folder( parent_path, filename, flag_recursive, parser); 435 | } 436 | else 437 | { 438 | fprintf(stderr, "Not a valid filter '%S'.", filter); 439 | } 440 | 441 | 442 | } 443 | 444 | // Cleanup the string parser 445 | delete parser; 446 | } 447 | 448 | 449 | return 0; 450 | } 451 | 452 | -------------------------------------------------------------------------------- /strings/strings.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #include "resource.h" 4 | 5 | #define APSTUDIO_READONLY_SYMBOLS 6 | ///////////////////////////////////////////////////////////////////////////// 7 | // 8 | // Generated from the TEXTINCLUDE 2 resource. 9 | // 10 | #include "winres.h" 11 | 12 | ///////////////////////////////////////////////////////////////////////////// 13 | #undef APSTUDIO_READONLY_SYMBOLS 14 | 15 | ///////////////////////////////////////////////////////////////////////////// 16 | // English (United States) resources 17 | 18 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 19 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 20 | #pragma code_page(1252) 21 | 22 | #ifdef APSTUDIO_INVOKED 23 | ///////////////////////////////////////////////////////////////////////////// 24 | // 25 | // TEXTINCLUDE 26 | // 27 | 28 | 1 TEXTINCLUDE 29 | BEGIN 30 | "resource.h\0" 31 | END 32 | 33 | 2 TEXTINCLUDE 34 | BEGIN 35 | "#include ""winres.h""\r\n" 36 | "\0" 37 | END 38 | 39 | 3 TEXTINCLUDE 40 | BEGIN 41 | "\r\n" 42 | "\0" 43 | END 44 | 45 | #endif // APSTUDIO_INVOKED 46 | 47 | 48 | ///////////////////////////////////////////////////////////////////////////// 49 | // 50 | // Version 51 | // 52 | 53 | VS_VERSION_INFO VERSIONINFO 54 | FILEVERSION 1,0,0,1 55 | PRODUCTVERSION 2,0,0,0 56 | FILEFLAGSMASK 0x3fL 57 | #ifdef _DEBUG 58 | FILEFLAGS 0x1L 59 | #else 60 | FILEFLAGS 0x0L 61 | #endif 62 | FILEOS 0x40004L 63 | FILETYPE 0x1L 64 | FILESUBTYPE 0x0L 65 | BEGIN 66 | BLOCK "StringFileInfo" 67 | BEGIN 68 | BLOCK "100904b0" 69 | BEGIN 70 | VALUE "CompanyName", "Geoff McDonald" 71 | VALUE "FileDescription", "Extract strings from binary content." 72 | VALUE "FileVersion", "2.0.0.0" 73 | VALUE "InternalName", "strings2.exe" 74 | VALUE "LegalCopyright", "Copyright (C) 2022" 75 | VALUE "OriginalFilename", "strings2.exe" 76 | VALUE "ProductName", "Strings2" 77 | VALUE "ProductVersion", "2.0.0.0" 78 | END 79 | END 80 | BLOCK "VarFileInfo" 81 | BEGIN 82 | VALUE "Translation", 0x1009, 1200 83 | END 84 | END 85 | 86 | #endif // English (United States) resources 87 | ///////////////////////////////////////////////////////////////////////////// 88 | 89 | 90 | 91 | #ifndef APSTUDIO_INVOKED 92 | ///////////////////////////////////////////////////////////////////////////// 93 | // 94 | // Generated from the TEXTINCLUDE 3 resource. 95 | // 96 | 97 | 98 | ///////////////////////////////////////////////////////////////////////////// 99 | #endif // not APSTUDIO_INVOKED 100 | 101 | -------------------------------------------------------------------------------- /strings/strings.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 15 | 18 | 19 | 20 | 21 | 22 | 30 | 33 | 36 | 39 | 42 | 45 | 56 | 59 | 62 | 65 | 74 | 77 | 80 | 83 | 86 | 89 | 92 | 95 | 96 | 103 | 106 | 109 | 112 | 115 | 119 | 130 | 133 | 136 | 139 | 147 | 150 | 153 | 156 | 159 | 162 | 165 | 168 | 169 | 177 | 180 | 183 | 186 | 189 | 192 | 203 | 206 | 209 | 212 | 222 | 225 | 228 | 231 | 234 | 237 | 240 | 243 | 244 | 252 | 255 | 258 | 261 | 264 | 268 | 279 | 282 | 285 | 288 | 298 | 301 | 304 | 307 | 310 | 313 | 316 | 319 | 320 | 321 | 322 | 323 | 324 | 329 | 332 | 333 | 336 | 337 | 340 | 341 | 344 | 345 | 348 | 351 | 355 | 356 | 359 | 363 | 364 | 367 | 371 | 372 | 375 | 379 | 380 | 381 | 384 | 385 | 388 | 389 | 390 | 395 | 398 | 399 | 402 | 403 | 406 | 407 | 410 | 411 | 414 | 415 | 418 | 419 | 422 | 423 | 426 | 427 | 430 | 431 | 434 | 435 | 436 | 441 | 442 | 445 | 446 | 447 | 448 | 449 | 450 | -------------------------------------------------------------------------------- /strings/strings.vcproj.glmcdona-PC.glmcdona.user: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | 35 | 36 | 39 | 63 | 64 | 67 | 91 | 92 | 95 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /strings/strings.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {12872240-F930-4859-8FE1-16ED68B57411} 23 | strings 24 | Win32Proj 25 | 10.0 26 | 27 | 28 | 29 | Application 30 | v142 31 | Unicode 32 | true 33 | 34 | 35 | Application 36 | v142 37 | Static 38 | Unicode 39 | 40 | 41 | Application 42 | v142 43 | Unicode 44 | true 45 | 46 | 47 | Application 48 | v142 49 | Unicode 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | <_ProjectFileVersion>16.0.32002.118 69 | 70 | 71 | $(SolutionDir)$(Configuration)\ 72 | $(Configuration)\ 73 | true 74 | 75 | 76 | $(SolutionDir)$(Platform)\$(Configuration)\ 77 | $(Platform)\$(Configuration)\ 78 | true 79 | 80 | 81 | $(SolutionDir)$(Configuration)\ 82 | $(Configuration)\ 83 | false 84 | 85 | 86 | $(SolutionDir)$(Platform)\$(Configuration)\ 87 | $(Platform)\$(Configuration)\ 88 | false 89 | 90 | 91 | 92 | Disabled 93 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 94 | false 95 | EnableFastChecks 96 | MultiThreadedDebug 97 | Use 98 | Level3 99 | EditAndContinue 100 | stdcpp20 101 | stdc17 102 | 103 | 104 | -L/usr/lib -lstdc++ %(AdditionalOptions) 105 | Shlwapi.lib;%(AdditionalDependencies) 106 | true 107 | Console 108 | MachineX86 109 | true 110 | 111 | 112 | 113 | 114 | X64 115 | 116 | 117 | Disabled 118 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 119 | false 120 | EnableFastChecks 121 | MultiThreadedDebug 122 | Use 123 | Level3 124 | ProgramDatabase 125 | stdcpp20 126 | stdc17 127 | 128 | 129 | Shlwapi.lib;%(AdditionalDependencies) 130 | true 131 | Console 132 | MachineX64 133 | true 134 | 135 | 136 | 137 | 138 | MaxSpeed 139 | true 140 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 141 | MultiThreaded 142 | true 143 | Use 144 | Level3 145 | ProgramDatabase 146 | stdcpp20 147 | stdc17 148 | 149 | 150 | Shlwapi.lib;%(AdditionalDependencies) 151 | true 152 | Console 153 | true 154 | true 155 | MachineX86 156 | true 157 | 158 | 159 | 160 | 161 | X64 162 | 163 | 164 | MaxSpeed 165 | true 166 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 167 | MultiThreaded 168 | true 169 | Use 170 | Level3 171 | ProgramDatabase 172 | stdcpp20 173 | stdc17 174 | 175 | 176 | Shlwapi.lib;%(AdditionalDependencies) 177 | true 178 | Console 179 | true 180 | true 181 | MachineX64 182 | true 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | Create 194 | Create 195 | Create 196 | Create 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | -------------------------------------------------------------------------------- /strings/strings.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files 44 | 45 | 46 | 47 | 48 | Header Files 49 | 50 | 51 | Header Files 52 | 53 | 54 | Header Files 55 | 56 | 57 | Header Files 58 | 59 | 60 | Header Files 61 | 62 | 63 | Header Files 64 | 65 | 66 | Header Files 67 | 68 | 69 | Header Files 70 | 71 | 72 | Header Files 73 | 74 | 75 | Header Files 76 | 77 | 78 | Header Files 79 | 80 | 81 | Header Files 82 | 83 | 84 | Header Files 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | Resource Files 93 | 94 | 95 | -------------------------------------------------------------------------------- /strings/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // The following macros define the minimum required platform. The minimum required platform 4 | // is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run 5 | // your application. The macros work by enabling all features available on platform versions up to and 6 | // including the version specified. 7 | 8 | // Modify the following defines if you have to target a platform prior to the ones specified below. 9 | // Refer to MSDN for the latest info on corresponding values for different platforms. 10 | #ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. 11 | #define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows. 12 | #endif 13 | 14 | -------------------------------------------------------------------------------- /x64/Debug/strings.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glmcdona/strings2/38630f3b058d48043d426adf80a3e1fcd715ad7c/x64/Debug/strings.exe -------------------------------------------------------------------------------- /x64/Debug/strings.ilk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glmcdona/strings2/38630f3b058d48043d426adf80a3e1fcd715ad7c/x64/Debug/strings.ilk -------------------------------------------------------------------------------- /x64/Debug/strings.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glmcdona/strings2/38630f3b058d48043d426adf80a3e1fcd715ad7c/x64/Debug/strings.pdb -------------------------------------------------------------------------------- /x64/Release/strings - Copy (2).exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glmcdona/strings2/38630f3b058d48043d426adf80a3e1fcd715ad7c/x64/Release/strings - Copy (2).exe -------------------------------------------------------------------------------- /x64/Release/strings - Copy.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glmcdona/strings2/38630f3b058d48043d426adf80a3e1fcd715ad7c/x64/Release/strings - Copy.exe -------------------------------------------------------------------------------- /x64/Release/strings.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glmcdona/strings2/38630f3b058d48043d426adf80a3e1fcd715ad7c/x64/Release/strings.exe -------------------------------------------------------------------------------- /x64/Release/strings.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glmcdona/strings2/38630f3b058d48043d426adf80a3e1fcd715ad7c/x64/Release/strings.pdb --------------------------------------------------------------------------------