├── .gitignore ├── LZMA ├── LzFind.c ├── LzFind.h ├── LzHash.h ├── LzmaDec.c ├── LzmaDec.h ├── LzmaEnc.c ├── LzmaEnc.h └── Types.h ├── LoaderTest ├── LoaderTest.cpp ├── LoaderTest.vcxproj └── LoaderTest.vcxproj.filters ├── PETest ├── PETest.cpp ├── PETest.vcxproj └── PETest.vcxproj.filters ├── Packer.sln ├── Packer ├── Packer.vcxproj ├── Packer.vcxproj.filters ├── PackerMain.cpp ├── PackerMain.h └── Win32Entry.cpp ├── Runtime ├── Allocator.cpp ├── Allocator.h ├── File.h ├── FormatBase.h ├── Image.cpp ├── Image.h ├── Option.cpp ├── Option.h ├── PEFormat.cpp ├── PEFormat.h ├── PEHeader.h └── Signature.h ├── Util ├── DataSource.h ├── List.h ├── Map.h ├── SharedPtr.h ├── String.h ├── TypeTraits.h ├── Util.h └── Vector.h ├── Win32 ├── MSVCHelper.cpp ├── Stub │ ├── Stage1 │ │ ├── Stage1.cpp │ │ ├── Stage1.vcxproj │ │ └── Stage1.vcxproj.filters │ ├── Stage2 │ │ ├── Stage2.cpp │ │ ├── Stage2.vcxproj │ │ └── Stage2.vcxproj.filters │ ├── StubData.h │ ├── Stubgen │ │ ├── Stubgen.cpp │ │ ├── Stubgen.vcxproj │ │ └── Stubgen.vcxproj.filters │ └── Win32Stub.h ├── Win32File.cpp ├── Win32File.h ├── Win32Loader.cpp ├── Win32Loader.h ├── Win32NativeHelper.cpp ├── Win32NativeHelper.h ├── Win32Structure.h ├── Win32SysCall.cpp └── Win32SysCall.h └── fnv1a.py /.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 | x64/ 14 | build/ 15 | [Bb]in/ 16 | [Oo]bj/ 17 | 18 | # MSTest test Results 19 | [Tt]est[Rr]esult*/ 20 | [Bb]uild[Ll]og.* 21 | 22 | *_i.c 23 | *_p.c 24 | *.ilk 25 | *.meta 26 | *.obj 27 | *.pch 28 | *.pdb 29 | *.pgc 30 | *.pgd 31 | *.rsp 32 | *.sbr 33 | *.tlb 34 | *.tli 35 | *.tlh 36 | *.tmp 37 | *.tmp_proj 38 | *.log 39 | *.vspscc 40 | *.vssscc 41 | .builds 42 | *.pidb 43 | *.log 44 | *.scc 45 | 46 | # Visual C++ cache files 47 | ipch/ 48 | *.aps 49 | *.ncb 50 | *.opensdf 51 | *.sdf 52 | *.cachefile 53 | 54 | # Visual Studio profiler 55 | *.psess 56 | *.vsp 57 | *.vspx 58 | 59 | # Guidance Automation Toolkit 60 | *.gpState 61 | 62 | # ReSharper is a .NET coding add-in 63 | _ReSharper*/ 64 | *.[Rr]e[Ss]harper 65 | 66 | # TeamCity is a build add-in 67 | _TeamCity* 68 | 69 | # DotCover is a Code Coverage Tool 70 | *.dotCover 71 | 72 | # NCrunch 73 | *.ncrunch* 74 | .*crunch*.local.xml 75 | 76 | # Installshield output folder 77 | [Ee]xpress/ 78 | 79 | # DocProject is a documentation generator add-in 80 | DocProject/buildhelp/ 81 | DocProject/Help/*.HxT 82 | DocProject/Help/*.HxC 83 | DocProject/Help/*.hhc 84 | DocProject/Help/*.hhk 85 | DocProject/Help/*.hhp 86 | DocProject/Help/Html2 87 | DocProject/Help/html 88 | 89 | # Click-Once directory 90 | publish/ 91 | 92 | # Publish Web Output 93 | *.Publish.xml 94 | *.pubxml 95 | 96 | # NuGet Packages Directory 97 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 98 | #packages/ 99 | 100 | # Windows Azure Build Output 101 | csx 102 | *.build.csdef 103 | 104 | # Windows Store app package directory 105 | AppPackages/ 106 | 107 | # Others 108 | sql/ 109 | *.Cache 110 | ClientBin/ 111 | [Ss]tyle[Cc]op.* 112 | ~$* 113 | *~ 114 | *.dbmdl 115 | *.[Pp]ublish.xml 116 | *.pfx 117 | *.publishsettings 118 | 119 | # RIA/Silverlight projects 120 | Generated_Code/ 121 | 122 | # Backup & report files from converting an old project file to a newer 123 | # Visual Studio version. Backup files are not needed, because we have git ;-) 124 | _UpgradeReport_Files/ 125 | Backup*/ 126 | UpgradeLog*.XML 127 | UpgradeLog*.htm 128 | 129 | # SQL Server files 130 | App_Data/*.mdf 131 | App_Data/*.ldf 132 | 133 | # ========================= 134 | # Windows detritus 135 | # ========================= 136 | 137 | # Windows image file caches 138 | Thumbs.db 139 | ehthumbs.db 140 | 141 | # Folder config file 142 | Desktop.ini 143 | 144 | # Recycle Bin used on file shares 145 | $RECYCLE.BIN/ 146 | 147 | # Mac crap 148 | .DS_Store 149 | 150 | *.pyc -------------------------------------------------------------------------------- /LZMA/LzFind.h: -------------------------------------------------------------------------------- 1 | /* LzFind.h -- Match finder for LZ algorithms 2 | 2009-04-22 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __LZ_FIND_H 5 | #define __LZ_FIND_H 6 | 7 | #include "Types.h" 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | typedef UInt32 CLzRef; 14 | 15 | typedef struct _CMatchFinder 16 | { 17 | Byte *buffer; 18 | UInt32 pos; 19 | UInt32 posLimit; 20 | UInt32 streamPos; 21 | UInt32 lenLimit; 22 | 23 | UInt32 cyclicBufferPos; 24 | UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ 25 | 26 | UInt32 matchMaxLen; 27 | CLzRef *hash; 28 | CLzRef *son; 29 | UInt32 hashMask; 30 | UInt32 cutValue; 31 | 32 | Byte *bufferBase; 33 | ISeqInStream *stream; 34 | int streamEndWasReached; 35 | 36 | UInt32 blockSize; 37 | UInt32 keepSizeBefore; 38 | UInt32 keepSizeAfter; 39 | 40 | UInt32 numHashBytes; 41 | int directInput; 42 | size_t directInputRem; 43 | int btMode; 44 | int bigHash; 45 | UInt32 historySize; 46 | UInt32 fixedHashSize; 47 | UInt32 hashSizeSum; 48 | UInt32 numSons; 49 | SRes result; 50 | UInt32 crc[256]; 51 | } CMatchFinder; 52 | 53 | #define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) 54 | #define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)]) 55 | 56 | #define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) 57 | 58 | int MatchFinder_NeedMove(CMatchFinder *p); 59 | Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); 60 | void MatchFinder_MoveBlock(CMatchFinder *p); 61 | void MatchFinder_ReadIfRequired(CMatchFinder *p); 62 | 63 | void MatchFinder_Construct(CMatchFinder *p); 64 | 65 | /* Conditions: 66 | historySize <= 3 GB 67 | keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB 68 | */ 69 | int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, 70 | UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, 71 | ISzAlloc *alloc); 72 | void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); 73 | void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); 74 | void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); 75 | 76 | UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, 77 | UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, 78 | UInt32 *distances, UInt32 maxLen); 79 | 80 | /* 81 | Conditions: 82 | Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. 83 | Mf_GetPointerToCurrentPos_Func's result must be used only before any other function 84 | */ 85 | 86 | typedef void (*Mf_Init_Func)(void *object); 87 | typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index); 88 | typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); 89 | typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); 90 | typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); 91 | typedef void (*Mf_Skip_Func)(void *object, UInt32); 92 | 93 | typedef struct _IMatchFinder 94 | { 95 | Mf_Init_Func Init; 96 | Mf_GetIndexByte_Func GetIndexByte; 97 | Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; 98 | Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; 99 | Mf_GetMatches_Func GetMatches; 100 | Mf_Skip_Func Skip; 101 | } IMatchFinder; 102 | 103 | void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); 104 | 105 | void MatchFinder_Init(CMatchFinder *p); 106 | UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); 107 | UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); 108 | void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); 109 | void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); 110 | 111 | #ifdef __cplusplus 112 | } 113 | #endif 114 | 115 | #endif 116 | -------------------------------------------------------------------------------- /LZMA/LzHash.h: -------------------------------------------------------------------------------- 1 | /* LzHash.h -- HASH functions for LZ algorithms 2 | 2009-02-07 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __LZ_HASH_H 5 | #define __LZ_HASH_H 6 | 7 | #define kHash2Size (1 << 10) 8 | #define kHash3Size (1 << 16) 9 | #define kHash4Size (1 << 20) 10 | 11 | #define kFix3HashSize (kHash2Size) 12 | #define kFix4HashSize (kHash2Size + kHash3Size) 13 | #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) 14 | 15 | #define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8); 16 | 17 | #define HASH3_CALC { \ 18 | UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ 19 | hash2Value = temp & (kHash2Size - 1); \ 20 | hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } 21 | 22 | #define HASH4_CALC { \ 23 | UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ 24 | hash2Value = temp & (kHash2Size - 1); \ 25 | hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ 26 | hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; } 27 | 28 | #define HASH5_CALC { \ 29 | UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ 30 | hash2Value = temp & (kHash2Size - 1); \ 31 | hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ 32 | hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \ 33 | hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \ 34 | hash4Value &= (kHash4Size - 1); } 35 | 36 | /* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ 37 | #define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; 38 | 39 | 40 | #define MT_HASH2_CALC \ 41 | hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); 42 | 43 | #define MT_HASH3_CALC { \ 44 | UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ 45 | hash2Value = temp & (kHash2Size - 1); \ 46 | hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } 47 | 48 | #define MT_HASH4_CALC { \ 49 | UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ 50 | hash2Value = temp & (kHash2Size - 1); \ 51 | hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ 52 | hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /LZMA/LzmaDec.h: -------------------------------------------------------------------------------- 1 | /* LzmaDec.h -- LZMA Decoder 2 | 2009-02-07 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __LZMA_DEC_H 5 | #define __LZMA_DEC_H 6 | 7 | #include "Types.h" 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | /* #define _LZMA_PROB32 */ 14 | /* _LZMA_PROB32 can increase the speed on some CPUs, 15 | but memory usage for CLzmaDec::probs will be doubled in that case */ 16 | 17 | #ifdef _LZMA_PROB32 18 | #define CLzmaProb UInt32 19 | #else 20 | #define CLzmaProb UInt16 21 | #endif 22 | 23 | 24 | /* ---------- LZMA Properties ---------- */ 25 | 26 | #define LZMA_PROPS_SIZE 5 27 | 28 | typedef struct _CLzmaProps 29 | { 30 | unsigned lc, lp, pb; 31 | UInt32 dicSize; 32 | } CLzmaProps; 33 | 34 | /* LzmaProps_Decode - decodes properties 35 | Returns: 36 | SZ_OK 37 | SZ_ERROR_UNSUPPORTED - Unsupported properties 38 | */ 39 | 40 | SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); 41 | 42 | 43 | /* ---------- LZMA Decoder state ---------- */ 44 | 45 | /* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. 46 | Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ 47 | 48 | #define LZMA_REQUIRED_INPUT_MAX 20 49 | 50 | typedef struct 51 | { 52 | CLzmaProps prop; 53 | CLzmaProb *probs; 54 | Byte *dic; 55 | const Byte *buf; 56 | UInt32 range, code; 57 | SizeT dicPos; 58 | SizeT dicBufSize; 59 | UInt32 processedPos; 60 | UInt32 checkDicSize; 61 | unsigned state; 62 | UInt32 reps[4]; 63 | unsigned remainLen; 64 | int needFlush; 65 | int needInitState; 66 | UInt32 numProbs; 67 | unsigned tempBufSize; 68 | Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; 69 | } CLzmaDec; 70 | 71 | #define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } 72 | 73 | void LzmaDec_Init(CLzmaDec *p); 74 | 75 | /* There are two types of LZMA streams: 76 | 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. 77 | 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ 78 | 79 | typedef enum 80 | { 81 | LZMA_FINISH_ANY, /* finish at any point */ 82 | LZMA_FINISH_END /* block must be finished at the end */ 83 | } ELzmaFinishMode; 84 | 85 | /* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! 86 | 87 | You must use LZMA_FINISH_END, when you know that current output buffer 88 | covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. 89 | 90 | If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, 91 | and output value of destLen will be less than output buffer size limit. 92 | You can check status result also. 93 | 94 | You can use multiple checks to test data integrity after full decompression: 95 | 1) Check Result and "status" variable. 96 | 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. 97 | 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. 98 | You must use correct finish mode in that case. */ 99 | 100 | typedef enum 101 | { 102 | LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ 103 | LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ 104 | LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ 105 | LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ 106 | LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ 107 | } ELzmaStatus; 108 | 109 | /* ELzmaStatus is used only as output value for function call */ 110 | 111 | 112 | /* ---------- Interfaces ---------- */ 113 | 114 | /* There are 3 levels of interfaces: 115 | 1) Dictionary Interface 116 | 2) Buffer Interface 117 | 3) One Call Interface 118 | You can select any of these interfaces, but don't mix functions from different 119 | groups for same object. */ 120 | 121 | 122 | /* There are two variants to allocate state for Dictionary Interface: 123 | 1) LzmaDec_Allocate / LzmaDec_Free 124 | 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs 125 | You can use variant 2, if you set dictionary buffer manually. 126 | For Buffer Interface you must always use variant 1. 127 | 128 | LzmaDec_Allocate* can return: 129 | SZ_OK 130 | SZ_ERROR_MEM - Memory allocation error 131 | SZ_ERROR_UNSUPPORTED - Unsupported properties 132 | */ 133 | 134 | SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); 135 | void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); 136 | 137 | SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); 138 | void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); 139 | 140 | /* ---------- Dictionary Interface ---------- */ 141 | 142 | /* You can use it, if you want to eliminate the overhead for data copying from 143 | dictionary to some other external buffer. 144 | You must work with CLzmaDec variables directly in this interface. 145 | 146 | STEPS: 147 | LzmaDec_Constr() 148 | LzmaDec_Allocate() 149 | for (each new stream) 150 | { 151 | LzmaDec_Init() 152 | while (it needs more decompression) 153 | { 154 | LzmaDec_DecodeToDic() 155 | use data from CLzmaDec::dic and update CLzmaDec::dicPos 156 | } 157 | } 158 | LzmaDec_Free() 159 | */ 160 | 161 | /* LzmaDec_DecodeToDic 162 | 163 | The decoding to internal dictionary buffer (CLzmaDec::dic). 164 | You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! 165 | 166 | finishMode: 167 | It has meaning only if the decoding reaches output limit (dicLimit). 168 | LZMA_FINISH_ANY - Decode just dicLimit bytes. 169 | LZMA_FINISH_END - Stream must be finished after dicLimit. 170 | 171 | Returns: 172 | SZ_OK 173 | status: 174 | LZMA_STATUS_FINISHED_WITH_MARK 175 | LZMA_STATUS_NOT_FINISHED 176 | LZMA_STATUS_NEEDS_MORE_INPUT 177 | LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK 178 | SZ_ERROR_DATA - Data error 179 | */ 180 | 181 | SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, 182 | const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); 183 | 184 | 185 | /* ---------- Buffer Interface ---------- */ 186 | 187 | /* It's zlib-like interface. 188 | See LzmaDec_DecodeToDic description for information about STEPS and return results, 189 | but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need 190 | to work with CLzmaDec variables manually. 191 | 192 | finishMode: 193 | It has meaning only if the decoding reaches output limit (*destLen). 194 | LZMA_FINISH_ANY - Decode just destLen bytes. 195 | LZMA_FINISH_END - Stream must be finished after (*destLen). 196 | */ 197 | 198 | SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, 199 | const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); 200 | 201 | 202 | /* ---------- One Call Interface ---------- */ 203 | 204 | /* LzmaDecode 205 | 206 | finishMode: 207 | It has meaning only if the decoding reaches output limit (*destLen). 208 | LZMA_FINISH_ANY - Decode just destLen bytes. 209 | LZMA_FINISH_END - Stream must be finished after (*destLen). 210 | 211 | Returns: 212 | SZ_OK 213 | status: 214 | LZMA_STATUS_FINISHED_WITH_MARK 215 | LZMA_STATUS_NOT_FINISHED 216 | LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK 217 | SZ_ERROR_DATA - Data error 218 | SZ_ERROR_MEM - Memory allocation error 219 | SZ_ERROR_UNSUPPORTED - Unsupported properties 220 | SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). 221 | */ 222 | 223 | SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, 224 | const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, 225 | ELzmaStatus *status, ISzAlloc *alloc); 226 | 227 | #ifdef __cplusplus 228 | } 229 | #endif 230 | 231 | #endif 232 | -------------------------------------------------------------------------------- /LZMA/LzmaEnc.h: -------------------------------------------------------------------------------- 1 | /* LzmaEnc.h -- LZMA Encoder 2 | 2009-02-07 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __LZMA_ENC_H 5 | #define __LZMA_ENC_H 6 | 7 | #define _7ZIP_ST //XXX dlunch: Only single threaded 8 | #include "Types.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #define LZMA_PROPS_SIZE 5 15 | 16 | typedef struct _CLzmaEncProps 17 | { 18 | int level; /* 0 <= level <= 9 */ 19 | UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version 20 | (1 << 12) <= dictSize <= (1 << 30) for 64-bit version 21 | default = (1 << 24) */ 22 | int lc; /* 0 <= lc <= 8, default = 3 */ 23 | int lp; /* 0 <= lp <= 4, default = 0 */ 24 | int pb; /* 0 <= pb <= 4, default = 2 */ 25 | int algo; /* 0 - fast, 1 - normal, default = 1 */ 26 | int fb; /* 5 <= fb <= 273, default = 32 */ 27 | int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */ 28 | int numHashBytes; /* 2, 3 or 4, default = 4 */ 29 | UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */ 30 | unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */ 31 | int numThreads; /* 1 or 2, default = 2 */ 32 | } CLzmaEncProps; 33 | 34 | void LzmaEncProps_Init(CLzmaEncProps *p); 35 | void LzmaEncProps_Normalize(CLzmaEncProps *p); 36 | UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); 37 | 38 | 39 | /* ---------- CLzmaEncHandle Interface ---------- */ 40 | 41 | /* LzmaEnc_* functions can return the following exit codes: 42 | Returns: 43 | SZ_OK - OK 44 | SZ_ERROR_MEM - Memory allocation error 45 | SZ_ERROR_PARAM - Incorrect paramater in props 46 | SZ_ERROR_WRITE - Write callback error. 47 | SZ_ERROR_PROGRESS - some break from progress callback 48 | SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) 49 | */ 50 | 51 | typedef void * CLzmaEncHandle; 52 | 53 | CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc); 54 | void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig); 55 | SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); 56 | SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); 57 | SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, 58 | ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); 59 | SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, 60 | int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); 61 | 62 | /* ---------- One Call Interface ---------- */ 63 | 64 | /* LzmaEncode 65 | Return code: 66 | SZ_OK - OK 67 | SZ_ERROR_MEM - Memory allocation error 68 | SZ_ERROR_PARAM - Incorrect paramater 69 | SZ_ERROR_OUTPUT_EOF - output buffer overflow 70 | SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) 71 | */ 72 | 73 | SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, 74 | const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, 75 | ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); 76 | 77 | #ifdef __cplusplus 78 | } 79 | #endif 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /LZMA/Types.h: -------------------------------------------------------------------------------- 1 | /* Types.h -- Basic types 2 | 2010-10-09 : Igor Pavlov : Public domain */ 3 | //Modified slightly by dlunch, removing windows.h inclusion when _WIN32 defined. 4 | 5 | #ifndef __7Z_TYPES_H 6 | #define __7Z_TYPES_H 7 | 8 | #include 9 | 10 | #ifndef EXTERN_C_BEGIN 11 | #ifdef __cplusplus 12 | #define EXTERN_C_BEGIN extern "C" { 13 | #define EXTERN_C_END } 14 | #else 15 | #define EXTERN_C_BEGIN 16 | #define EXTERN_C_END 17 | #endif 18 | #endif 19 | 20 | EXTERN_C_BEGIN 21 | 22 | #define SZ_OK 0 23 | 24 | #define SZ_ERROR_DATA 1 25 | #define SZ_ERROR_MEM 2 26 | #define SZ_ERROR_CRC 3 27 | #define SZ_ERROR_UNSUPPORTED 4 28 | #define SZ_ERROR_PARAM 5 29 | #define SZ_ERROR_INPUT_EOF 6 30 | #define SZ_ERROR_OUTPUT_EOF 7 31 | #define SZ_ERROR_READ 8 32 | #define SZ_ERROR_WRITE 9 33 | #define SZ_ERROR_PROGRESS 10 34 | #define SZ_ERROR_FAIL 11 35 | #define SZ_ERROR_THREAD 12 36 | 37 | #define SZ_ERROR_ARCHIVE 16 38 | #define SZ_ERROR_NO_ARCHIVE 17 39 | 40 | typedef int SRes; 41 | typedef int WRes; 42 | 43 | #ifndef RINOK 44 | #define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } 45 | #endif 46 | 47 | typedef unsigned char Byte; 48 | typedef short Int16; 49 | typedef unsigned short UInt16; 50 | 51 | #ifdef _LZMA_UINT32_IS_ULONG 52 | typedef long Int32; 53 | typedef unsigned long UInt32; 54 | #else 55 | typedef int Int32; 56 | typedef unsigned int UInt32; 57 | #endif 58 | 59 | #ifdef _SZ_NO_INT_64 60 | 61 | /* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. 62 | NOTES: Some code will work incorrectly in that case! */ 63 | 64 | typedef long Int64; 65 | typedef unsigned long UInt64; 66 | 67 | #else 68 | 69 | #if defined(_MSC_VER) || defined(__BORLANDC__) 70 | typedef __int64 Int64; 71 | typedef unsigned __int64 UInt64; 72 | #define UINT64_CONST(n) n 73 | #else 74 | typedef long long int Int64; 75 | typedef unsigned long long int UInt64; 76 | #define UINT64_CONST(n) n ## ULL 77 | #endif 78 | 79 | #endif 80 | 81 | #ifdef _LZMA_NO_SYSTEM_SIZE_T 82 | typedef UInt32 SizeT; 83 | #else 84 | typedef size_t SizeT; 85 | #endif 86 | 87 | typedef int Bool; 88 | #define True 1 89 | #define False 0 90 | 91 | 92 | #ifdef _WIN32 93 | #define MY_STD_CALL __stdcall 94 | #else 95 | #define MY_STD_CALL 96 | #endif 97 | 98 | #ifdef _MSC_VER 99 | 100 | #if _MSC_VER >= 1300 101 | #define MY_NO_INLINE __declspec(noinline) 102 | #else 103 | #define MY_NO_INLINE 104 | #endif 105 | 106 | #define MY_CDECL __cdecl 107 | #define MY_FAST_CALL __fastcall 108 | 109 | #else 110 | 111 | #define MY_CDECL 112 | #define MY_FAST_CALL 113 | 114 | #endif 115 | 116 | 117 | /* The following interfaces use first parameter as pointer to structure */ 118 | 119 | typedef struct 120 | { 121 | Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */ 122 | } IByteIn; 123 | 124 | typedef struct 125 | { 126 | void (*Write)(void *p, Byte b); 127 | } IByteOut; 128 | 129 | typedef struct 130 | { 131 | SRes (*Read)(void *p, void *buf, size_t *size); 132 | /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. 133 | (output(*size) < input(*size)) is allowed */ 134 | } ISeqInStream; 135 | 136 | /* it can return SZ_ERROR_INPUT_EOF */ 137 | SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); 138 | SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); 139 | SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); 140 | 141 | typedef struct 142 | { 143 | size_t (*Write)(void *p, const void *buf, size_t size); 144 | /* Returns: result - the number of actually written bytes. 145 | (result < size) means error */ 146 | } ISeqOutStream; 147 | 148 | typedef enum 149 | { 150 | SZ_SEEK_SET = 0, 151 | SZ_SEEK_CUR = 1, 152 | SZ_SEEK_END = 2 153 | } ESzSeek; 154 | 155 | typedef struct 156 | { 157 | SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ 158 | SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); 159 | } ISeekInStream; 160 | 161 | typedef struct 162 | { 163 | SRes (*Look)(void *p, const void **buf, size_t *size); 164 | /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. 165 | (output(*size) > input(*size)) is not allowed 166 | (output(*size) < input(*size)) is allowed */ 167 | SRes (*Skip)(void *p, size_t offset); 168 | /* offset must be <= output(*size) of Look */ 169 | 170 | SRes (*Read)(void *p, void *buf, size_t *size); 171 | /* reads directly (without buffer). It's same as ISeqInStream::Read */ 172 | SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); 173 | } ILookInStream; 174 | 175 | SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); 176 | SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); 177 | 178 | /* reads via ILookInStream::Read */ 179 | SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); 180 | SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); 181 | 182 | #define LookToRead_BUF_SIZE (1 << 14) 183 | 184 | typedef struct 185 | { 186 | ILookInStream s; 187 | ISeekInStream *realStream; 188 | size_t pos; 189 | size_t size; 190 | Byte buf[LookToRead_BUF_SIZE]; 191 | } CLookToRead; 192 | 193 | void LookToRead_CreateVTable(CLookToRead *p, int lookahead); 194 | void LookToRead_Init(CLookToRead *p); 195 | 196 | typedef struct 197 | { 198 | ISeqInStream s; 199 | ILookInStream *realStream; 200 | } CSecToLook; 201 | 202 | void SecToLook_CreateVTable(CSecToLook *p); 203 | 204 | typedef struct 205 | { 206 | ISeqInStream s; 207 | ILookInStream *realStream; 208 | } CSecToRead; 209 | 210 | void SecToRead_CreateVTable(CSecToRead *p); 211 | 212 | typedef struct 213 | { 214 | SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); 215 | /* Returns: result. (result != SZ_OK) means break. 216 | Value (UInt64)(Int64)-1 for size means unknown value. */ 217 | } ICompressProgress; 218 | 219 | typedef struct 220 | { 221 | void *(*Alloc)(void *p, size_t size); 222 | void (*Free)(void *p, void *address); /* address can be 0 */ 223 | } ISzAlloc; 224 | 225 | #define IAlloc_Alloc(p, size) (p)->Alloc((p), size) 226 | #define IAlloc_Free(p, a) (p)->Free((p), a) 227 | 228 | #ifdef _WIN32 229 | 230 | #define CHAR_PATH_SEPARATOR '\\' 231 | #define WCHAR_PATH_SEPARATOR L'\\' 232 | #define STRING_PATH_SEPARATOR "\\" 233 | #define WSTRING_PATH_SEPARATOR L"\\" 234 | 235 | #else 236 | 237 | #define CHAR_PATH_SEPARATOR '/' 238 | #define WCHAR_PATH_SEPARATOR L'/' 239 | #define STRING_PATH_SEPARATOR "/" 240 | #define WSTRING_PATH_SEPARATOR L"/" 241 | 242 | #endif 243 | 244 | EXTERN_C_END 245 | 246 | #endif 247 | -------------------------------------------------------------------------------- /LoaderTest/LoaderTest.cpp: -------------------------------------------------------------------------------- 1 | #include "../Win32/Win32NativeHelper.h" 2 | #include "../Win32/Win32Loader.h" 3 | #include "../Runtime/PEFormat.h" 4 | 5 | List *loadedFiles_; 6 | List loadImport(SharedPtr input) 7 | { 8 | List result; 9 | for(auto &i : input->getImports()) 10 | { 11 | bool alreadyLoaded = false; 12 | String fileName = i.libraryName; 13 | for(auto &j : *loadedFiles_) 14 | if(j == fileName) 15 | { 16 | alreadyLoaded = true; 17 | break; 18 | } 19 | if(alreadyLoaded) 20 | continue; 21 | 22 | if(input->isSystemLibrary(fileName)) 23 | continue; 24 | SharedPtr import = FormatBase::loadImport(fileName, input->getInfo().architecture); 25 | loadedFiles_->push_back(import->getFileName()); 26 | result.push_back(import->toImage()); 27 | 28 | List dependencies = loadImport(import); 29 | result.insert(result.end(), dependencies.begin(), dependencies.end()); 30 | } 31 | 32 | return result; 33 | } 34 | 35 | void Entry() 36 | { 37 | Win32NativeHelper::get()->init(); 38 | loadedFiles_ = new List; 39 | 40 | List arguments = Win32NativeHelper::get()->getArgumentList(); 41 | 42 | SharedPtr file = File::open(*(++ arguments.begin())); 43 | SharedPtr input = MakeShared(); 44 | input->load(file, false); 45 | input->setFileName(file->getFileName()); 46 | input->setFilePath(file->getFilePath()); 47 | 48 | Vector serialized = input->toImage().serialize(); 49 | Image image = Image::unserialize(serialized.getView(0, 0), nullptr); 50 | 51 | Win32Loader loader(std::move(image), loadImport(input)); 52 | loader.execute(); 53 | } -------------------------------------------------------------------------------- /LoaderTest/LoaderTest.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {3473CDAA-D7D8-4D0A-A588-DC12790F47C6} 15 | Win32Proj 16 | LoaderTest 17 | 18 | 19 | 20 | Application 21 | true 22 | v120 23 | Unicode 24 | 25 | 26 | Application 27 | false 28 | v120 29 | true 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | false 45 | 46 | 47 | false 48 | false 49 | 50 | 51 | 52 | 53 | 54 | Level3 55 | Disabled 56 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 57 | false 58 | Default 59 | false 60 | false 61 | 62 | 63 | Console 64 | true 65 | true 66 | Entry 67 | 68 | 69 | 70 | 71 | Level3 72 | 73 | 74 | MaxSpeed 75 | true 76 | true 77 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 78 | false 79 | false 80 | false 81 | 82 | 83 | Console 84 | true 85 | true 86 | true 87 | true 88 | Entry 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | false 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /LoaderTest/LoaderTest.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;hh;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;mfcribbon-ms 15 | 16 | 17 | {c5df296e-e876-4232-83b4-e021fb6a3877} 18 | 19 | 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 | LZMA 44 | 45 | 46 | LZMA 47 | 48 | 49 | LZMA 50 | 51 | 52 | Source Files 53 | 54 | 55 | Source Files 56 | 57 | 58 | 59 | 60 | LZMA 61 | 62 | 63 | LZMA 64 | 65 | 66 | LZMA 67 | 68 | 69 | LZMA 70 | 71 | 72 | LZMA 73 | 74 | 75 | -------------------------------------------------------------------------------- /PETest/PETest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | int main() 6 | { 7 | std::cout << "Hello, World"; 8 | MessageBox(NULL, L"test", L"test", MB_OK); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /PETest/PETest.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {37C23896-C95D-43B8-B809-907689B51CC6} 15 | Win32Proj 16 | PETest 17 | 18 | 19 | 20 | Application 21 | true 22 | v120 23 | Unicode 24 | 25 | 26 | Application 27 | false 28 | v120 29 | true 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | 45 | 46 | false 47 | 48 | 49 | 50 | 51 | 52 | Level3 53 | Disabled 54 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 55 | true 56 | 57 | 58 | Console 59 | true 60 | user32.dll 61 | 62 | 63 | 64 | 65 | Level3 66 | 67 | 68 | MaxSpeed 69 | true 70 | true 71 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 72 | true 73 | 74 | 75 | Console 76 | true 77 | true 78 | true 79 | user32.dll 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /PETest/PETest.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;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /Packer.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.21005.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Packer", "Packer\Packer.vcxproj", "{130F5158-8E3C-48C5-ABD7-3BC93A4DFB34}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PETest", "PETest\PETest.vcxproj", "{37C23896-C95D-43B8-B809-907689B51CC6}" 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Stage1", "Win32\Stub\Stage1\Stage1.vcxproj", "{A0359D6F-C025-4AA1-B44C-E5AB028BB89A}" 11 | EndProject 12 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Stage2", "Win32\Stub\Stage2\Stage2.vcxproj", "{EA3BC0AC-A01B-43E3-932C-B0F719BC57CC}" 13 | EndProject 14 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Stubgen", "Win32\Stub\Stubgen\Stubgen.vcxproj", "{DF6E3D45-C2BB-4E18-80AC-567DC2FF727D}" 15 | EndProject 16 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LoaderTest", "LoaderTest\LoaderTest.vcxproj", "{3473CDAA-D7D8-4D0A-A588-DC12790F47C6}" 17 | EndProject 18 | Global 19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 20 | Debug|Win32 = Debug|Win32 21 | Release|Win32 = Release|Win32 22 | EndGlobalSection 23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 24 | {130F5158-8E3C-48C5-ABD7-3BC93A4DFB34}.Debug|Win32.ActiveCfg = Debug|Win32 25 | {130F5158-8E3C-48C5-ABD7-3BC93A4DFB34}.Debug|Win32.Build.0 = Debug|Win32 26 | {130F5158-8E3C-48C5-ABD7-3BC93A4DFB34}.Release|Win32.ActiveCfg = Release|Win32 27 | {130F5158-8E3C-48C5-ABD7-3BC93A4DFB34}.Release|Win32.Build.0 = Release|Win32 28 | {37C23896-C95D-43B8-B809-907689B51CC6}.Debug|Win32.ActiveCfg = Debug|Win32 29 | {37C23896-C95D-43B8-B809-907689B51CC6}.Debug|Win32.Build.0 = Debug|Win32 30 | {37C23896-C95D-43B8-B809-907689B51CC6}.Release|Win32.ActiveCfg = Release|Win32 31 | {37C23896-C95D-43B8-B809-907689B51CC6}.Release|Win32.Build.0 = Release|Win32 32 | {A0359D6F-C025-4AA1-B44C-E5AB028BB89A}.Debug|Win32.ActiveCfg = Debug|Win32 33 | {A0359D6F-C025-4AA1-B44C-E5AB028BB89A}.Debug|Win32.Build.0 = Debug|Win32 34 | {A0359D6F-C025-4AA1-B44C-E5AB028BB89A}.Release|Win32.ActiveCfg = Release|Win32 35 | {A0359D6F-C025-4AA1-B44C-E5AB028BB89A}.Release|Win32.Build.0 = Release|Win32 36 | {EA3BC0AC-A01B-43E3-932C-B0F719BC57CC}.Debug|Win32.ActiveCfg = Debug|Win32 37 | {EA3BC0AC-A01B-43E3-932C-B0F719BC57CC}.Debug|Win32.Build.0 = Debug|Win32 38 | {EA3BC0AC-A01B-43E3-932C-B0F719BC57CC}.Release|Win32.ActiveCfg = Release|Win32 39 | {EA3BC0AC-A01B-43E3-932C-B0F719BC57CC}.Release|Win32.Build.0 = Release|Win32 40 | {DF6E3D45-C2BB-4E18-80AC-567DC2FF727D}.Debug|Win32.ActiveCfg = Debug|Win32 41 | {DF6E3D45-C2BB-4E18-80AC-567DC2FF727D}.Debug|Win32.Build.0 = Debug|Win32 42 | {DF6E3D45-C2BB-4E18-80AC-567DC2FF727D}.Release|Win32.ActiveCfg = Release|Win32 43 | {DF6E3D45-C2BB-4E18-80AC-567DC2FF727D}.Release|Win32.Build.0 = Release|Win32 44 | {3473CDAA-D7D8-4D0A-A588-DC12790F47C6}.Debug|Win32.ActiveCfg = Debug|Win32 45 | {3473CDAA-D7D8-4D0A-A588-DC12790F47C6}.Debug|Win32.Build.0 = Debug|Win32 46 | {3473CDAA-D7D8-4D0A-A588-DC12790F47C6}.Release|Win32.ActiveCfg = Release|Win32 47 | {3473CDAA-D7D8-4D0A-A588-DC12790F47C6}.Release|Win32.Build.0 = Release|Win32 48 | EndGlobalSection 49 | GlobalSection(SolutionProperties) = preSolution 50 | HideSolutionNode = FALSE 51 | EndGlobalSection 52 | EndGlobal 53 | -------------------------------------------------------------------------------- /Packer/Packer.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {130F5158-8E3C-48C5-ABD7-3BC93A4DFB34} 15 | Win32Proj 16 | Packer 17 | 18 | 19 | 20 | Application 21 | true 22 | v120 23 | Unicode 24 | 25 | 26 | Application 27 | false 28 | v120 29 | true 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | false 45 | 46 | 47 | false 48 | false 49 | 50 | 51 | 52 | 53 | 54 | Level3 55 | Disabled 56 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 57 | false 58 | false 59 | Default 60 | false 61 | false 62 | 63 | 64 | Console 65 | true 66 | WindowsEntry 67 | true 68 | 0x00400000 69 | true 70 | false 71 | 72 | 73 | 74 | 75 | Level3 76 | 77 | 78 | Full 79 | true 80 | true 81 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 82 | false 83 | false 84 | false 85 | true 86 | true 87 | Speed 88 | StreamingSIMDExtensions2 89 | 90 | 91 | Console 92 | false 93 | true 94 | true 95 | true 96 | WindowsEntry 97 | UseLinkTimeCodeGeneration 98 | 99 | 100 | true 101 | false 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | false 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /Packer/Packer.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;mfcribbon-ms 15 | 16 | 17 | {0294b92d-8da7-4cf2-9009-98d2e1240003} 18 | 19 | 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 | Source Files 47 | 48 | 49 | LZMA 50 | 51 | 52 | LZMA 53 | 54 | 55 | LZMA 56 | 57 | 58 | Source Files 59 | 60 | 61 | Source Files 62 | 63 | 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 | Header Files 88 | 89 | 90 | Header Files 91 | 92 | 93 | Header Files 94 | 95 | 96 | Header Files 97 | 98 | 99 | Header Files 100 | 101 | 102 | Header Files 103 | 104 | 105 | Header Files 106 | 107 | 108 | Header Files 109 | 110 | 111 | Header Files 112 | 113 | 114 | Header Files 115 | 116 | 117 | Header Files 118 | 119 | 120 | Header Files 121 | 122 | 123 | LZMA 124 | 125 | 126 | LZMA 127 | 128 | 129 | LZMA 130 | 131 | 132 | LZMA 133 | 134 | 135 | LZMA 136 | 137 | 138 | Header Files 139 | 140 | 141 | Header Files 142 | 143 | 144 | -------------------------------------------------------------------------------- /Packer/PackerMain.cpp: -------------------------------------------------------------------------------- 1 | #include "PackerMain.h" 2 | 3 | #include "../Runtime/FormatBase.h" 4 | #include "../Runtime/PEFormat.h" 5 | #include "../Win32/Stub/Win32Stub.h" 6 | #include "../Win32/Stub/StubData.h" 7 | #include "../Util/Vector.h" 8 | #include "../Runtime/Signature.h" 9 | #include "../Win32/Win32NativeHelper.h" 10 | 11 | PackerMain::PackerMain(const Option &option) : option_(option) 12 | { 13 | } 14 | 15 | int PackerMain::process() 16 | { 17 | processFile(option_.getInputFile(), option_.getOutputFile()); 18 | 19 | return 0; 20 | } 21 | 22 | List PackerMain::loadImport(SharedPtr input) 23 | { 24 | List result; 25 | for(auto &i : input->getImports()) 26 | { 27 | bool alreadyLoaded = false; 28 | String fileName = i.libraryName; 29 | for(auto &j : loadedFiles_) 30 | if(j == fileName) 31 | { 32 | alreadyLoaded = true; 33 | break; 34 | } 35 | if(alreadyLoaded) 36 | continue; 37 | 38 | if(input->isSystemLibrary(fileName)) 39 | continue; 40 | SharedPtr import = FormatBase::loadImport(fileName, input->getInfo().architecture); 41 | loadedFiles_.push_back(import->getFileName()); 42 | result.push_back(import->toImage()); 43 | 44 | List dependencies = loadImport(import); 45 | result.insert(result.end(), dependencies.begin(), dependencies.end()); 46 | } 47 | 48 | return result; 49 | } 50 | 51 | void PackerMain::processFile(SharedPtr inputf, SharedPtr output) 52 | { 53 | SharedPtr input; 54 | { 55 | SharedPtr view = inputf->getView(0, 0); 56 | uint8_t *fileData = view->get(); 57 | if(*(reinterpret_cast(fileData)) == IMAGE_DOS_SIGNATURE) 58 | input = MakeShared(); 59 | else 60 | return; 61 | } 62 | input->load(inputf, false); 63 | input->setFileName(inputf->getFileName()); 64 | input->setFilePath(inputf->getFilePath()); 65 | loadedFiles_.push_back(input->getFileName()); 66 | List imports = loadImport(input); 67 | 68 | outputPE(input->toImage(), imports, output); 69 | } 70 | 71 | void PackerMain::outputPE(Image &image, const List imports, SharedPtr output) 72 | { 73 | PEFormat resultFormat; 74 | Vector stub(win32StubSize); 75 | simpleRLEDecompress(win32StubData, stub.get()); 76 | resultFormat.load(stub.asDataSource(), false); 77 | 78 | List
resultSections(resultFormat.getSections()); 79 | uint64_t lastAddress; 80 | for(auto &i : resultSections) 81 | lastAddress = i.baseAddress + i.size; 82 | 83 | Vector mainData(image.serialize()); 84 | uint32_t seed = Win32NativeHelper::get()->getRandomValue(); 85 | simpleCrypt(seed, &mainData[0], mainData.size()); 86 | 87 | Section mainSection; 88 | mainSection.baseAddress = multipleOf(static_cast(lastAddress), 0x1000); 89 | mainSection.flag = SectionFlagData | SectionFlagRead; 90 | mainSection.name.assign(reinterpret_cast(&seed), reinterpret_cast(&seed) + 4); 91 | mainSection.data = mainData.getView(0, mainData.size()); 92 | mainSection.size = mainData.size(); 93 | resultSections.push_back(mainSection); 94 | 95 | lastAddress = mainSection.baseAddress + mainSection.size; 96 | 97 | Vector impData; 98 | uint32_t impCount = imports.size(); 99 | impData.append(reinterpret_cast(&impCount), sizeof(impCount)); 100 | for(auto &i : imports) 101 | impData.append(i.serialize()); 102 | seed = Win32NativeHelper::get()->getRandomValue(); 103 | simpleCrypt(seed, &impData[0], impData.size()); 104 | 105 | Section importSection; 106 | importSection.baseAddress = multipleOf(static_cast(lastAddress), 0x1000); 107 | importSection.flag = SectionFlagData | SectionFlagRead; 108 | importSection.name.assign(reinterpret_cast(&seed), reinterpret_cast(&seed) + 4); 109 | importSection.data = impData.getView(0, impData.size()); 110 | importSection.size = impData.size(); 111 | resultSections.push_back(importSection); 112 | 113 | resultFormat.setSections(resultSections); 114 | 115 | output->resize(resultFormat.estimateSize()); 116 | resultFormat.save(output); 117 | } -------------------------------------------------------------------------------- /Packer/PackerMain.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Runtime/Option.h" 4 | #include "../Util/List.h" 5 | #include "../Util/SharedPtr.h" 6 | 7 | class File; 8 | class FormatBase; 9 | struct Image; 10 | 11 | class PackerMain 12 | { 13 | private: 14 | const Option &option_; 15 | List loadedFiles_; 16 | 17 | void outputPE(Image &image, const List imports, SharedPtr output); 18 | void processFile(SharedPtr inputf, SharedPtr output); 19 | List loadImport(SharedPtr input); 20 | public: 21 | PackerMain(const Option &option); 22 | int process(); 23 | }; 24 | -------------------------------------------------------------------------------- /Packer/Win32Entry.cpp: -------------------------------------------------------------------------------- 1 | #include "PackerMain.h" 2 | #include "../Win32/Win32NativeHelper.h" 3 | #include "../Util/Util.h" 4 | 5 | void WindowsEntry() 6 | { 7 | Win32NativeHelper::get()->init(); 8 | 9 | List arguments = Win32NativeHelper::get()->getArgumentList(); 10 | 11 | PackerMain(Option(arguments)).process(); 12 | } -------------------------------------------------------------------------------- /Runtime/Allocator.cpp: -------------------------------------------------------------------------------- 1 | #include "Allocator.h" 2 | 3 | #include "../Win32/Win32SysCall.h" 4 | #include "../Util/Util.h" 5 | 6 | #include 7 | 8 | #pragma pack(push, 1) 9 | struct MemoryInfo 10 | { 11 | unsigned int inUse : 1; 12 | #ifdef _WIN64 13 | unsigned int bucketPtr : 63; 14 | #else 15 | unsigned int bucketPtr : 31; 16 | #endif 17 | }; 18 | struct Bucket 19 | { 20 | Bucket *nextBucket; 21 | size_t usedCnt; 22 | uint8_t *lastPtr; 23 | uint8_t bucketData[1]; 24 | }; 25 | #pragma pack(pop) 26 | 27 | #define BIGHEAP_TAG 0xdeadbeef 28 | #define BUCKET_COUNT 13 29 | const uint16_t bucketSizes[BUCKET_COUNT] = {4, 16, 32, 64, 128, 512, 1024, 2048, 4096, 8192, 16384, 32768, 0}; 30 | Bucket *bucket[BUCKET_COUNT]; 31 | const size_t bucketCapacity[BUCKET_COUNT] = {0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0}; 32 | Bucket *lastBucket[BUCKET_COUNT]; 33 | 34 | uint8_t *allocateVirtual(size_t size) 35 | { 36 | return reinterpret_cast(Win32SystemCaller::get()->allocateVirtual(0, multipleOf(size, 4096), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)); 37 | } 38 | 39 | bool freeVirtual(void *ptr) 40 | { 41 | return Win32SystemCaller::get()->freeVirtual(ptr); 42 | } 43 | 44 | uint8_t *searchEmpty(Bucket *bucket, uint8_t *ptr, size_t bucketSize, size_t capacity) 45 | { 46 | while(true) 47 | { 48 | if(ptr + sizeof(MemoryInfo) + bucketSize > reinterpret_cast(bucket) + capacity) 49 | break; 50 | MemoryInfo *info = reinterpret_cast(ptr); 51 | if(!info->inUse) 52 | { 53 | info->inUse = 1; 54 | info->bucketPtr = reinterpret_cast(bucket); 55 | bucket->usedCnt ++; 56 | bucket->lastPtr = ptr + sizeof(MemoryInfo) + bucketSize; 57 | return ptr + sizeof(MemoryInfo); 58 | } 59 | ptr += sizeof(MemoryInfo) + bucketSize; 60 | } 61 | return nullptr; 62 | } 63 | 64 | uint8_t *allocate(Bucket *bucket, size_t bucketSize, size_t capacity) 65 | { 66 | if(bucket->usedCnt > capacity / (bucketSize + sizeof(MemoryInfo)) - 1) 67 | return nullptr; 68 | uint8_t *result = searchEmpty(bucket, bucket->lastPtr, bucketSize, capacity); 69 | if(result) 70 | return result; 71 | 72 | uint8_t *ptr = bucket->bucketData + bucket->usedCnt * (bucketSize + sizeof(MemoryInfo)); 73 | result = searchEmpty(bucket, ptr, bucketSize, capacity); 74 | if(result) 75 | return result; 76 | 77 | return searchEmpty(bucket, bucket->bucketData, bucketSize, capacity); 78 | } 79 | 80 | void *heapAlloc(size_t size) 81 | { 82 | size_t bucketNo; 83 | for(bucketNo = 0; bucketNo < BUCKET_COUNT; bucketNo ++) 84 | if(bucketSizes[bucketNo] >= size || bucketSizes[bucketNo] == 0) 85 | break; 86 | 87 | if(bucketSizes[bucketNo] == 0) 88 | { 89 | uint8_t *alloc = allocateVirtual(multipleOf(size + 4, 4096)); 90 | *reinterpret_cast(alloc) = BIGHEAP_TAG; 91 | return alloc + 4; 92 | } 93 | if(lastBucket[bucketNo]) 94 | { 95 | uint8_t *result = allocate(lastBucket[bucketNo], bucketSizes[bucketNo], bucketCapacity[bucketNo]); 96 | if(result) 97 | return result; 98 | } 99 | Bucket **currentBucket = &bucket[bucketNo]; 100 | while(true) 101 | { 102 | if(!*currentBucket) 103 | { 104 | size_t newSize = multipleOf(bucketCapacity[bucketNo], 4096); 105 | *currentBucket = reinterpret_cast(allocateVirtual(newSize)); 106 | (*currentBucket)->lastPtr = (*currentBucket)->bucketData; 107 | lastBucket[bucketNo] = (*currentBucket); 108 | } 109 | 110 | uint8_t *result = allocate(*currentBucket, bucketSizes[bucketNo], bucketCapacity[bucketNo]); 111 | if(result) 112 | return result; 113 | currentBucket = &((*currentBucket)->nextBucket); 114 | } 115 | } 116 | 117 | void heapFree(void *ptr) 118 | { 119 | if(!ptr) 120 | return; 121 | if(*reinterpret_cast(reinterpret_cast(ptr) - 4) == BIGHEAP_TAG && ((reinterpret_cast(ptr) - 4) & 0xFFFF) == 0 && freeVirtual(ptr)) 122 | return; 123 | 124 | MemoryInfo *infoPtr = reinterpret_cast(reinterpret_cast(ptr) - sizeof(MemoryInfo)); 125 | infoPtr->inUse = 0; 126 | reinterpret_cast(infoPtr->bucketPtr)->usedCnt --; 127 | reinterpret_cast(infoPtr->bucketPtr)->lastPtr = reinterpret_cast(infoPtr); 128 | } -------------------------------------------------------------------------------- /Runtime/Allocator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void *heapAlloc(size_t size); 4 | void heapFree(void *ptr); -------------------------------------------------------------------------------- /Runtime/File.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "../Util/String.h" 6 | #include "../Util/SharedPtr.h" 7 | #include "../Util/DataSource.h" 8 | 9 | class File : public DataSource, public EnableSharedFromThis 10 | { 11 | public: 12 | File() {} 13 | virtual ~File() {} 14 | 15 | static SharedPtr open(const String &filename, bool write = false); 16 | 17 | virtual String getFileName() = 0; 18 | virtual String getFilePath() = 0; 19 | virtual void *getHandle() = 0; 20 | virtual void resize(uint64_t newSize) = 0; 21 | virtual SharedPtr getView(uint64_t offset, size_t size) = 0; 22 | virtual void write(const uint8_t *data, size_t size) = 0; 23 | 24 | void write(const Vector &data) 25 | { 26 | write(data.get(), data.size()); 27 | } 28 | template 29 | void write(T *data, size_t size) 30 | { 31 | write(reinterpret_cast(data), size); 32 | } 33 | 34 | static String combinePath(const String &directory, const String &filename); 35 | static bool isPathExists(const String &path); 36 | }; 37 | 38 | -------------------------------------------------------------------------------- /Runtime/FormatBase.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Image.h" 4 | #include "../Util/List.h" 5 | #include "../Util/String.h" 6 | #include "../Util/SharedPtr.h" 7 | #include "../Util/DataSource.h" 8 | 9 | class FormatBase 10 | { 11 | public: 12 | FormatBase() {} 13 | virtual ~FormatBase() {} 14 | 15 | virtual bool load(SharedPtr source, bool fromMemory) = 0; 16 | virtual void setFileName(const String &fileName) = 0; 17 | virtual void setFilePath(const String &filePath) = 0; 18 | virtual const String &getFileName() const = 0; 19 | virtual const String &getFilePath() const = 0; 20 | virtual Image toImage() = 0; 21 | virtual const List &getImports() = 0; 22 | virtual const List &getExports() = 0; 23 | virtual const ImageInfo &getInfo() const = 0; 24 | virtual const List &getRelocations() = 0; 25 | virtual const List
&getSections() const = 0; 26 | 27 | virtual void setSections(const List
§ions) = 0; 28 | virtual void setRelocations(const List &relocations) = 0; 29 | virtual void setImageInfo(const ImageInfo &info) = 0; 30 | 31 | virtual void save(SharedPtr target) = 0; 32 | virtual size_t estimateSize() const = 0; 33 | 34 | virtual bool isSystemLibrary(const String &filename) = 0; 35 | 36 | static SharedPtr loadImport(const String &filename, int architecture = -1); 37 | }; -------------------------------------------------------------------------------- /Runtime/Image.cpp: -------------------------------------------------------------------------------- 1 | #include "Image.h" 2 | 3 | #include "Allocator.h" 4 | 5 | #include "../LZMA/LzmaEnc.h" 6 | #include "../LZMA/LzmaDec.h" 7 | 8 | //lzma allocator functions 9 | static void *SzAlloc(void *, size_t size) 10 | { 11 | return heapAlloc(size); 12 | } 13 | static void SzFree(void *, void *address) 14 | { 15 | heapFree(address); 16 | } 17 | static ISzAlloc g_Alloc = {SzAlloc, SzFree}; 18 | 19 | //both serialization and unserialization are done on machine with same endian. 20 | 21 | template 22 | void appendToVector(Vector &dst, const T &src) 23 | { 24 | dst.append(reinterpret_cast(&src), sizeof(T)); 25 | } 26 | 27 | template 28 | void appendToVector(Vector &dst, const Vector &src) 29 | { 30 | appendToVector(dst, static_cast(src.size())); 31 | dst.append(src); 32 | } 33 | 34 | void appendToVector(Vector &dst, const uint8_t *data, size_t size) 35 | { 36 | appendToVector(dst, static_cast(size)); 37 | dst.append(data, size); 38 | } 39 | 40 | template <> 41 | void appendToVector(Vector &dst, const String &src) 42 | { 43 | appendToVector(dst, static_cast(src.length())); 44 | dst.append(reinterpret_cast(src.c_str()), src.length()); 45 | } 46 | 47 | Vector Image::serialize() const 48 | { 49 | Vector result; 50 | #define A(...) appendToVector(result, __VA_ARGS__); 51 | 52 | //imageinfo 53 | A(info.architecture); 54 | A(info.baseAddress); 55 | A(info.entryPoint); 56 | A(info.flag); 57 | A(info.platformData); 58 | A(info.platformData1); 59 | A(info.size); 60 | 61 | A(fileName); 62 | 63 | A(static_cast(exports.size())); 64 | for(auto &i : exports) 65 | { 66 | A(i.address); 67 | A(i.forward); 68 | A(i.name); 69 | A(i.nameHash); 70 | A(i.ordinal); 71 | } 72 | 73 | A(static_cast(sections.size())); 74 | for(auto &i : sections) 75 | { 76 | A(i.name); 77 | A(i.baseAddress); 78 | A(i.size); 79 | A(i.flag); 80 | } 81 | 82 | A(static_cast(imports.size())); 83 | for(auto &i : imports) 84 | { 85 | A(i.libraryName); 86 | A(static_cast(i.functions.size())); 87 | for(auto &j : i.functions) 88 | { 89 | A(j.iat); 90 | A(j.name); 91 | A(j.nameHash); 92 | A(j.ordinal); 93 | } 94 | } 95 | 96 | A(static_cast(relocations.size())); 97 | for(auto &i : relocations) 98 | A(i); 99 | 100 | for(auto &i : sections) 101 | { 102 | A(i.data->get(), i.data->size()); 103 | if((i.flag & SectionFlagCode) && i.data->size() > 5) 104 | { 105 | uint8_t *codeStart = result.end() - i.data->size(); 106 | for(size_t j = 0; j < i.data->size() - 5; j ++) 107 | { 108 | if(codeStart[j] == 0xE8 || codeStart[j] == 0xE9) //call rel32, jmp rel32 109 | { 110 | *reinterpret_cast(codeStart + j + 1) += (j + 5); 111 | j += 4; 112 | } 113 | else if(codeStart[j] == 0x0f && (codeStart[j + 1] >= 0x80 && codeStart[j + 1] <= 0x8f)) //conditional jmp rel32 114 | { 115 | *reinterpret_cast(codeStart + j + 2) += (j + 6); 116 | j += 5; 117 | } 118 | } 119 | } 120 | } 121 | 122 | A(header->get(), header->size()); 123 | 124 | #undef A 125 | 126 | CLzmaEncProps props; 127 | LzmaEncProps_Init(&props); 128 | 129 | props.numThreads = 1; 130 | LzmaEncProps_Normalize(&props); 131 | 132 | uint32_t sizeSize = sizeof(uint32_t) * 2; 133 | uint32_t propsSize = LZMA_PROPS_SIZE; 134 | uint32_t outSize = result.size() + result.size() / 40 + (1 << 12); //igor recommends (http://sourceforge.net/p/sevenzip/discussion/45798/thread/dd3b392c/) 135 | Vector compressed(outSize + propsSize + sizeSize); 136 | LzmaEncode(&compressed[propsSize + sizeSize], &outSize, &result[0], result.size(), &props, &compressed[sizeSize], &propsSize, 0, nullptr, &g_Alloc, &g_Alloc); 137 | 138 | *reinterpret_cast(&compressed[0]) = result.size(); 139 | *reinterpret_cast(&compressed[sizeof(uint32_t)]) = outSize; 140 | 141 | compressed.resize(outSize + propsSize + sizeSize); 142 | return compressed; 143 | } 144 | 145 | template 146 | T readFromVector(uint8_t *data, size_t &offset) 147 | { 148 | offset += sizeof(T); 149 | return *reinterpret_cast(data + offset - sizeof(T)); 150 | } 151 | 152 | template <> 153 | String readFromVector(uint8_t *data, size_t &offset) 154 | { 155 | uint32_t len = readFromVector(data, offset); 156 | String result(data + offset, data + offset + len); 157 | offset += len; 158 | return result; 159 | } 160 | 161 | template <> 162 | Vector readFromVector(uint8_t *data, size_t &offset) 163 | { 164 | uint32_t len = readFromVector(data, offset); 165 | Vector result(data + offset, data + offset + len); 166 | offset += len; 167 | return result; 168 | } 169 | 170 | template 171 | T readFromVector(uint8_t *data, size_t &offset, Vector original); 172 | 173 | template<> 174 | SharedPtr readFromVector(uint8_t *data, size_t &offset, Vector original) 175 | { 176 | uint32_t len = readFromVector(data, offset); 177 | offset += len; 178 | return original.getView(offset - len, len); 179 | } 180 | 181 | Image Image::unserialize(SharedPtr data_, size_t *processedSize) 182 | { 183 | uint32_t sizeSize = sizeof(uint32_t) * 2; 184 | uint32_t propsSize = LZMA_PROPS_SIZE; 185 | 186 | ELzmaStatus status; 187 | uint8_t *compressedData = data_->get(); 188 | uint32_t uncompressedSize = *reinterpret_cast(compressedData); 189 | uint32_t compressedSize = *reinterpret_cast(compressedData + sizeof(uint32_t)); 190 | Vector uncompressed(uncompressedSize); 191 | 192 | LzmaDecode(&uncompressed[0], &uncompressedSize, compressedData + sizeSize + propsSize, &compressedSize, compressedData + sizeSize, propsSize, LZMA_FINISH_ANY, &status, &g_Alloc); 193 | compressedSize += sizeSize + propsSize; 194 | uint8_t *data = &uncompressed[0]; 195 | size_t offset = 0; 196 | Image result; 197 | 198 | if(processedSize) 199 | *processedSize = compressedSize; 200 | 201 | #define R(t, ...) readFromVector(data, offset, __VA_ARGS__) 202 | result.info.architecture = R(ArchitectureType); 203 | result.info.baseAddress = R(uint64_t); 204 | result.info.entryPoint = R(uint64_t); 205 | result.info.flag = R(uint32_t); 206 | result.info.platformData = R(uint64_t); 207 | result.info.platformData1 = R(uint64_t); 208 | result.info.size = R(uint64_t); 209 | 210 | result.fileName = R(String); 211 | 212 | uint32_t exportLen = R(uint32_t); 213 | result.exports.reserve(exportLen); 214 | for(size_t i = 0; i < exportLen; ++ i) 215 | { 216 | ExportFunction item; 217 | item.address = R(uint64_t); 218 | item.forward = R(String); 219 | item.name = R(String); 220 | item.nameHash = R(uint32_t); 221 | item.ordinal = R(uint16_t); 222 | 223 | result.exports.push_back(std::move(item)); 224 | } 225 | 226 | uint32_t sectionLen = R(uint32_t); 227 | for(size_t i = 0; i < sectionLen; ++ i) 228 | { 229 | Section item; 230 | item.name = R(String); 231 | item.baseAddress = R(uint64_t); 232 | item.size = R(uint64_t); 233 | item.flag = R(uint32_t); 234 | 235 | result.sections.push_back(std::move(item)); 236 | } 237 | 238 | uint32_t importLen = R(uint32_t); 239 | for(size_t i = 0; i < importLen; ++ i) 240 | { 241 | Import item; 242 | item.libraryName = R(String); 243 | uint32_t functionLen = R(uint32_t); 244 | for(size_t j = 0; j < functionLen; ++ j) 245 | { 246 | ImportFunction function; 247 | function.iat = R(uint64_t); 248 | function.name = R(String); 249 | function.nameHash = R(uint32_t); 250 | function.ordinal = R(uint16_t); 251 | 252 | item.functions.push_back(std::move(function)); 253 | } 254 | 255 | result.imports.push_back(std::move(item)); 256 | } 257 | 258 | uint32_t relocationLen = R(uint32_t); 259 | for(size_t i = 0; i < relocationLen; ++ i) 260 | result.relocations.push_back(R(uint64_t)); 261 | 262 | for(auto &i : result.sections) 263 | { 264 | i.data = R(SharedPtr, uncompressed); 265 | if((i.flag & SectionFlagCode) && i.data->size() > 5) 266 | { 267 | uint8_t *codeStart = i.data->get(); 268 | for(size_t j = 0; j < i.data->size() - 5; j ++) 269 | { 270 | if(codeStart[j] == 0xE8 || codeStart[j] == 0xE9) //call rel32, jmp rel32 271 | { 272 | *reinterpret_cast(codeStart + j + 1) -= (j + 5); 273 | j += 4; 274 | } 275 | else if(codeStart[j] == 0x0f && (codeStart[j + 1] >= 0x80 && codeStart[j + 1] <= 0x8f)) //conditional jmp rel32 276 | { 277 | *reinterpret_cast(codeStart + j + 2) -= (j + 6); 278 | j += 5; 279 | } 280 | } 281 | } 282 | } 283 | 284 | result.header = R(SharedPtr, uncompressed); 285 | #undef R 286 | return result; 287 | } 288 | -------------------------------------------------------------------------------- /Runtime/Image.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "../Util/TypeTraits.h" 6 | #include "../Util/Vector.h" 7 | #include "../Util/List.h" 8 | #include "../Util/String.h" 9 | #include "../Util/DataSource.h" 10 | 11 | enum ArchitectureType 12 | { 13 | ArchitectureWin32 = 1, 14 | ArchitectureWin32AMD64 = 2, 15 | }; 16 | 17 | enum ImageFlag 18 | { 19 | ImageFlagLibrary = 1, 20 | }; 21 | 22 | struct ImageInfo 23 | { 24 | ArchitectureType architecture; 25 | uint64_t baseAddress; 26 | uint64_t entryPoint; 27 | uint64_t size; 28 | uint32_t flag; 29 | 30 | uint64_t platformData; //PE: security cookie 31 | uint64_t platformData1; //PE: tls entry 32 | }; 33 | 34 | enum SectionFlag 35 | { 36 | SectionFlagCode = 1, 37 | SectionFlagData = 2, 38 | SectionFlagUninitializedData = 4, 39 | SectionFlagRead = 8, 40 | SectionFlagWrite = 16, 41 | SectionFlagExecute = 32, 42 | }; 43 | 44 | struct Section 45 | { 46 | Section() {} 47 | Section(Section &&operand) : name(std::move(operand.name)), baseAddress(operand.baseAddress), size(operand.size), data(std::move(operand.data)), flag(operand.flag) {} 48 | const Section &operator =(Section &&operand) 49 | { 50 | name = std::move(operand.name); 51 | baseAddress = operand.baseAddress; 52 | size = operand.size; 53 | data = std::move(operand.data); 54 | flag = operand.flag; 55 | 56 | return *this; 57 | } 58 | 59 | const Section &operator =(const Section &operand) 60 | { 61 | name = operand.name; 62 | baseAddress = operand.baseAddress; 63 | size = operand.size; 64 | data = operand.data; 65 | flag = operand.flag; 66 | 67 | return *this; 68 | } 69 | String name; 70 | uint64_t baseAddress; 71 | uint64_t size; 72 | SharedPtr data; 73 | uint32_t flag; 74 | }; 75 | 76 | struct ImportFunction 77 | { 78 | ImportFunction() {} 79 | ImportFunction(ImportFunction &&operand) : ordinal(operand.ordinal), name(std::move(operand.name)), iat(operand.iat), nameHash(operand.nameHash) {} 80 | const ImportFunction &operator =(ImportFunction &&operand) 81 | { 82 | ordinal = operand.ordinal; 83 | name = std::move(operand.name); 84 | nameHash = operand.nameHash; 85 | iat = operand.iat; 86 | 87 | return *this; 88 | } 89 | uint16_t ordinal; 90 | String name; 91 | uint32_t nameHash; 92 | uint64_t iat; 93 | }; 94 | 95 | struct Import 96 | { 97 | Import() {} 98 | Import(Import &&operand) : libraryName(std::move(operand.libraryName)), functions(std::move(operand.functions)) {} 99 | const Import &operator =(Import &&operand) 100 | { 101 | libraryName = std::move(operand.libraryName); 102 | functions = std::move(operand.functions); 103 | 104 | return *this; 105 | } 106 | String libraryName; 107 | Vector functions; 108 | }; 109 | 110 | struct ExportFunction 111 | { 112 | ExportFunction() {} 113 | ExportFunction(ExportFunction &&operand) : ordinal(operand.ordinal), name(std::move(operand.name)), address(operand.address), forward(std::move(operand.forward)), nameHash(operand.nameHash) {} 114 | const ExportFunction &operator =(ExportFunction &&operand) 115 | { 116 | ordinal = operand.ordinal; 117 | name = std::move(operand.name); 118 | nameHash = operand.nameHash; 119 | address = operand.address; 120 | forward = std::move(operand.forward); 121 | 122 | return *this; 123 | } 124 | uint16_t ordinal; 125 | String name; 126 | uint32_t nameHash; 127 | uint64_t address; 128 | String forward; 129 | }; 130 | 131 | struct Image 132 | { 133 | Image() {} 134 | Image(Image &&operand) : 135 | info(operand.info), sections(std::move(operand.sections)), 136 | imports(std::move(operand.imports)), relocations(std::move(operand.relocations)), 137 | fileName(std::move(operand.fileName)), 138 | exports(std::move(operand.exports)), 139 | header(std::move(operand.header)){} 140 | const Image &operator =(Image &&operand) 141 | { 142 | info = std::move(operand.info); 143 | sections = std::move(operand.sections); 144 | imports = std::move(operand.imports); 145 | relocations = std::move(operand.relocations); 146 | fileName = std::move(operand.fileName); 147 | exports = std::move(operand.exports); 148 | header = std::move(operand.header); 149 | 150 | return *this; 151 | } 152 | ImageInfo info; 153 | String fileName; 154 | uint32_t nameExportLen; 155 | Vector exports; 156 | List
sections; 157 | List imports; 158 | List relocations; 159 | SharedPtr header; 160 | 161 | Vector serialize() const; 162 | static Image unserialize(SharedPtr data, size_t *processedSize); 163 | }; 164 | 165 | -------------------------------------------------------------------------------- /Runtime/Option.cpp: -------------------------------------------------------------------------------- 1 | #include "Option.h" 2 | 3 | #include "File.h" 4 | 5 | Option::Option(const List &args) 6 | { 7 | parseOptions(args); 8 | } 9 | 10 | bool Option::isBooleanOption(const String &optionName) 11 | { 12 | return false; 13 | } 14 | 15 | void Option::handleStringOption(const String &name, const String &value) 16 | { 17 | if(name == "o") 18 | outputFile_ = File::open(value, true); 19 | } 20 | 21 | void Option::parseOptions(List rawOptions) 22 | { 23 | auto &it = rawOptions.begin(); 24 | it ++; 25 | for(; it != rawOptions.end(); it ++) 26 | { 27 | if(it->length() > 0 && it->at(0) == '-') 28 | { 29 | String optionName = it->substr(1); 30 | if(isBooleanOption(optionName)) 31 | booleanOptions_[optionName] = true; 32 | else 33 | { 34 | it ++; 35 | if(it != rawOptions.end()) 36 | handleStringOption(optionName, *it); 37 | } 38 | } 39 | else 40 | inputFile_ = File::open(*it); 41 | } 42 | } 43 | 44 | SharedPtr Option::getInputFile() const 45 | { 46 | return inputFile_; 47 | } 48 | 49 | SharedPtr Option::getOutputFile() const 50 | { 51 | return outputFile_; 52 | } 53 | -------------------------------------------------------------------------------- /Runtime/Option.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Util/List.h" 4 | #include "../Util/Map.h" 5 | #include "../Util/String.h" 6 | #include "../Util/SharedPtr.h" 7 | 8 | class File; 9 | class Option 10 | { 11 | private: 12 | SharedPtr inputFile_; 13 | SharedPtr outputFile_; 14 | Map booleanOptions_; 15 | Map stringOptions_; 16 | 17 | void parseOptions(List rawOptions); 18 | void handleStringOption(const String &name, const String &value); 19 | bool isBooleanOption(const String &optionName); 20 | public: 21 | Option(const List &args); 22 | 23 | SharedPtr getInputFile() const; 24 | SharedPtr getOutputFile() const; 25 | }; 26 | -------------------------------------------------------------------------------- /Runtime/PEFormat.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "FormatBase.h" 4 | #include "File.h" 5 | #include "../Util/SharedPtr.h" 6 | #include "../Util/List.h" 7 | #include "../Util/DataSource.h" 8 | 9 | struct _IMAGE_DATA_DIRECTORY; 10 | typedef _IMAGE_DATA_DIRECTORY IMAGE_DATA_DIRECTORY; 11 | class PEFormat : public FormatBase 12 | { 13 | private: 14 | List
sections_; 15 | List imports_; 16 | List relocations_; 17 | List exports_; 18 | SharedPtr header_; 19 | ImageInfo info_; 20 | size_t dataDirectoryBase_; 21 | bool processedRelocation_; 22 | bool processedImport_; 23 | bool processedExport_; 24 | 25 | String fileName_; 26 | String filePath_; 27 | 28 | size_t loadHeader(SharedPtr source, bool fromMemory); 29 | void processRelocation(); 30 | void processImport(); 31 | void processExport(); 32 | uint8_t *getDataPointerOfRVA(uint32_t rva); 33 | String PEFormat::checkExportForwarder(uint64_t address, size_t exportTableBase, size_t exportTableSize); 34 | IMAGE_DATA_DIRECTORY *getDataDirectory(size_t index); 35 | public: 36 | PEFormat(); 37 | virtual ~PEFormat(); 38 | 39 | virtual bool load(SharedPtr source, bool fromMemory); 40 | virtual void setFileName(const String &fileName); 41 | virtual void setFilePath(const String &filePath); 42 | virtual const String &getFileName() const; 43 | virtual const String &getFilePath() const; 44 | virtual Image toImage(); 45 | virtual const List &getImports(); 46 | virtual const List &getExports(); 47 | virtual const ImageInfo &getInfo() const; 48 | virtual const List &getRelocations(); 49 | virtual const List
&getSections() const; 50 | 51 | virtual void setSections(const List
§ions); 52 | virtual void setRelocations(const List &relocations); 53 | virtual void setImageInfo(const ImageInfo &info); 54 | 55 | virtual void save(SharedPtr target); 56 | virtual size_t estimateSize() const; 57 | 58 | virtual bool isSystemLibrary(const String &filename); 59 | }; 60 | -------------------------------------------------------------------------------- /Runtime/Signature.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __GNUC__ 4 | #include 5 | #endif 6 | 7 | #if defined(__LITTLE_ENDIAN) || defined(_M_IX86) || defined(_M_AMD64) 8 | #define IMAGE_DOS_SIGNATURE 0x5A4D // MZ 9 | #define IMAGE_NT_SIGNATURE 0x00004550 // PE00 10 | #else 11 | #define IMAGE_DOS_SIGNATURE 0x4D5A // MZ 12 | #define IMAGE_NT_SIGNATURE 0x50450000 // PE00 13 | #endif -------------------------------------------------------------------------------- /Util/DataSource.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "SharedPtr.h" 5 | 6 | class DataView; 7 | class DataSource 8 | { 9 | public: 10 | virtual SharedPtr getView(uint64_t offset, size_t size) = 0; 11 | virtual uint8_t *map(uint64_t offset) = 0; 12 | virtual void unmap() = 0; 13 | }; 14 | 15 | class DataView 16 | { 17 | private: 18 | SharedPtr source_; 19 | uint64_t offset_; 20 | uint8_t *baseAddress_; 21 | size_t size_; 22 | public: 23 | DataView(SharedPtr source, uint64_t offset, size_t size) : source_(source), offset_(offset), size_(size), baseAddress_(source_->map(offset_)) {} 24 | virtual ~DataView() 25 | { 26 | if(baseAddress_) 27 | source_->unmap(); 28 | } 29 | 30 | void unmap() 31 | { 32 | if(baseAddress_) 33 | source_->unmap(); 34 | baseAddress_ = 0; 35 | } 36 | 37 | uint8_t *get() const 38 | { 39 | return baseAddress_; 40 | } 41 | 42 | size_t size() const 43 | { 44 | return size_; 45 | } 46 | 47 | SharedPtr getView(uint64_t offset, size_t size) const 48 | { 49 | return MakeShared(source_, offset_ + offset, size); 50 | } 51 | }; 52 | 53 | class MemoryDataSource : public DataSource, public EnableSharedFromThis 54 | { 55 | private: 56 | uint8_t *memory_; 57 | size_t size_; 58 | public: 59 | MemoryDataSource(uint8_t *memory, size_t size = 0) : memory_(memory), size_(size) {} 60 | virtual ~MemoryDataSource() {} 61 | 62 | virtual SharedPtr getView(uint64_t offset, size_t size = 0) 63 | { 64 | if(size == 0) 65 | size = size_; 66 | return MakeShared(sharedFromThis(), offset, size); 67 | } 68 | 69 | virtual uint8_t *map(uint64_t offset) 70 | { 71 | return memory_ + offset; 72 | } 73 | 74 | virtual void unmap() 75 | { 76 | 77 | } 78 | }; -------------------------------------------------------------------------------- /Util/List.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //replacement of std::list, to get rid of external dependency. 4 | 5 | #include "TypeTraits.h" 6 | 7 | template 8 | class List 9 | { 10 | private: 11 | struct ListNodeBase 12 | { 13 | ListNodeBase *next; 14 | ListNodeBase *prev; 15 | }; 16 | struct ListNode : public ListNodeBase 17 | { 18 | ValueType data; 19 | }; 20 | ListNodeBase *head_; 21 | 22 | template 23 | class ListIterator 24 | { 25 | friend class List; 26 | private: 27 | BaseType *item_; 28 | public: 29 | ListIterator(BaseType *item) : item_(item) {} 30 | 31 | ValueType &operator *() 32 | { 33 | return static_cast(item_)->data; 34 | } 35 | 36 | bool operator !=(const ListIterator &operand) const 37 | { 38 | return item_ != operand.item_; 39 | } 40 | 41 | ListIterator operator ++(int) 42 | { 43 | ListIterator result(item_->next); 44 | item_ = item_->next; 45 | return result; 46 | } 47 | 48 | ListIterator &operator ++() 49 | { 50 | item_ = item_->next; 51 | return *this; 52 | } 53 | 54 | ValueType *operator ->() 55 | { 56 | return &static_cast(item_)->data; 57 | } 58 | 59 | size_t operator -(const ListIterator &operand) const 60 | { 61 | size_t cnt = 0; 62 | BaseType *node = operand.item_; 63 | while(node != item_) 64 | { 65 | cnt ++; 66 | node = node->next; 67 | } 68 | return cnt; 69 | } 70 | }; 71 | 72 | void ensureHead_() 73 | { 74 | if(!head_) 75 | { 76 | head_ = new ListNodeBase(); 77 | head_->next = head_; 78 | head_->prev = head_; 79 | } 80 | } 81 | 82 | ListNode* appendNode_() 83 | { 84 | ensureHead_(); 85 | ListNode *item = new ListNode(); 86 | item->next = head_; 87 | item->prev = head_->prev; 88 | head_->prev->next = item; 89 | head_->prev = item; 90 | 91 | return item; 92 | } 93 | public: 94 | typedef ValueType value_type; 95 | typedef ListIterator const_iterator; 96 | typedef ListIterator iterator; 97 | List() : head_(nullptr) {} 98 | 99 | ~List() 100 | { 101 | clear(); 102 | } 103 | 104 | List(const List &other) : head_(nullptr) 105 | { 106 | *this = other; 107 | } 108 | 109 | List(List &&other) : head_(other.head_) 110 | { 111 | other.head_ = nullptr; 112 | } 113 | 114 | template 115 | List(InputIterator s, InputIterator e) 116 | { 117 | head_ = new ListNodeBase(); 118 | head_->next = head_; 119 | head_->prev = head_; 120 | 121 | for(; s != e; s ++) 122 | push_back(*s); 123 | } 124 | 125 | void clear() 126 | { 127 | if(head_) 128 | { 129 | ListNodeBase *item = head_->next; 130 | while(item->next != head_) 131 | { 132 | ListNode *item_ = static_cast(item); 133 | item = item->next; 134 | delete item_; 135 | } 136 | delete head_; 137 | } 138 | head_ = nullptr; 139 | } 140 | 141 | const List &operator =(List &&operand) 142 | { 143 | head_ = operand.head_; 144 | operand.head_ = nullptr; 145 | 146 | return *this; 147 | } 148 | 149 | const List &operator =(const List &operand) 150 | { 151 | if(!operand.head_) 152 | { 153 | clear(); 154 | return *this; 155 | } 156 | head_ = new ListNodeBase(); 157 | head_->next = head_; 158 | head_->prev = head_; 159 | 160 | ListNodeBase *item = operand.head_->next; 161 | while(item != operand.head_) 162 | { 163 | ListNode *item_ = static_cast(item); 164 | push_back(item_->data); 165 | item = item->next; 166 | } 167 | 168 | return *this; 169 | } 170 | 171 | iterator push_back(const value_type &data) 172 | { 173 | ListNode *item = appendNode_(); 174 | item->data = data; 175 | 176 | return iterator(item); 177 | } 178 | 179 | iterator push_back(value_type &&data) 180 | { 181 | ListNode *item = appendNode_(); 182 | item->data = std::move(data); 183 | 184 | return iterator(item); 185 | } 186 | 187 | iterator remove(iterator at) 188 | { 189 | if(at.item_->prev == nullptr && at.item_->next == nullptr) 190 | { 191 | delete at.item_; 192 | delete head_; 193 | head_ = nullptr; 194 | return iterator(nullptr); 195 | } 196 | ListNodeBase *item = at.item_; 197 | iterator next(item->next); 198 | 199 | item->prev->next = item->next; 200 | item->next->prev = item->prev; 201 | delete static_cast(item); 202 | return next; 203 | } 204 | 205 | template 206 | iterator insert(iterator at, InputIterator start, InputIterator end) 207 | { 208 | ensureHead_(); 209 | ListNode *position = static_cast(at.item_); 210 | for(; start != end; start ++) 211 | { 212 | ListNode *item = new ListNode(); 213 | item->next = position; 214 | item->data = *start; 215 | item->prev = position->prev; 216 | position->prev->next = item; 217 | position->prev = item; 218 | } 219 | return iterator(position); 220 | } 221 | 222 | const_iterator begin() const 223 | { 224 | if(!head_) 225 | return const_iterator(nullptr); 226 | return const_iterator(head_->next); 227 | } 228 | 229 | const_iterator end() const 230 | { 231 | if(!head_) 232 | return const_iterator(nullptr); 233 | return const_iterator(head_); 234 | } 235 | 236 | iterator begin() 237 | { 238 | if(!head_) 239 | return iterator(nullptr); 240 | return iterator(head_->next); 241 | } 242 | 243 | iterator end() 244 | { 245 | if(!head_) 246 | return iterator(nullptr); 247 | return iterator(head_); 248 | } 249 | 250 | size_t size() const 251 | { 252 | if(!head_) 253 | return 0; 254 | size_t size = 0; 255 | const ListNodeBase *item = head_; 256 | while(item->next != head_) 257 | { 258 | size ++; 259 | item = item->next; 260 | } 261 | return size; 262 | } 263 | }; -------------------------------------------------------------------------------- /Util/Map.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TypeTraits.h" 4 | 5 | template 6 | class DefaultComparator 7 | { 8 | public: 9 | bool operator ()(const ValueType &a, const ValueType &b) 10 | { 11 | return a < b; 12 | } 13 | }; 14 | 15 | template> 16 | class Map 17 | { 18 | private: 19 | struct MapNode 20 | { 21 | MapNode(const KeyType &key_, const ValueType &value_, MapNode *parent_) : left(nullptr), right(nullptr), key(key_), value(value_), parent(parent_) {} 22 | MapNode(const KeyType &key_, ValueType &&value_, MapNode *parent_) : left(nullptr), right(nullptr), key(key_), value(std::move(value_)), parent(parent_) {} 23 | MapNode *left; 24 | MapNode *right; 25 | MapNode *parent; 26 | KeyType key; 27 | ValueType value; 28 | }; 29 | MapNode *head_; 30 | 31 | template 32 | class MapIterator 33 | { 34 | private: 35 | NodeType *node_; 36 | Map *map_; 37 | public: 38 | MapIterator(NodeType *node, Map *map) : node_(node), map_(map) {} 39 | 40 | MapNode &operator *() 41 | { 42 | return *node_; 43 | } 44 | 45 | MapNode *operator ->() 46 | { 47 | return node_; 48 | } 49 | 50 | bool operator ==(const MapIterator &operand) 51 | { 52 | return node_ == operand.node_; 53 | } 54 | 55 | bool operator !=(const MapIterator &operand) 56 | { 57 | return node_ != operand.node_; 58 | } 59 | 60 | MapIterator &operator ++() 61 | { 62 | *this = map_->upper_bound(node_->key); 63 | return *this; 64 | } 65 | }; 66 | public: 67 | typedef ValueType value_type; 68 | typedef MapIterator iterator; 69 | typedef MapIterator const_iterator; 70 | 71 | private: 72 | template 73 | iterator insert_(const KeyType &key, InsertType value) 74 | { 75 | if(!head_) 76 | { 77 | head_ = new MapNode(key, value, nullptr); 78 | return iterator(nullptr, this); 79 | } 80 | MapNode *item = head_; 81 | while(true) 82 | { 83 | if(Comparator()(item->key, key)) 84 | { 85 | if(item->right) 86 | { 87 | item = item->right; 88 | continue; 89 | } 90 | item->right = new MapNode(key, value, item); 91 | } 92 | else 93 | { 94 | if(item->left) 95 | { 96 | item = item->left; 97 | continue; 98 | } 99 | item->left = new MapNode(key, value, item); 100 | } 101 | break; 102 | } 103 | return iterator(item, this); 104 | } 105 | 106 | template 107 | MapNode *find_(const KeyType &key) 108 | { 109 | if(!head_) 110 | return nullptr; 111 | MapNode *item = head_; 112 | while(Comparator()(item->key, key) || Comparator()(key, item->key)) //item->key < key or key > item->key => key != item->key 113 | { 114 | if(Comparator()(item->key, key)) 115 | { 116 | if(item->right) 117 | { 118 | item = item->right; 119 | continue; 120 | } 121 | else 122 | return nullptr; 123 | } 124 | else 125 | { 126 | if(item->left) 127 | { 128 | item = item->left; 129 | continue; 130 | } 131 | else 132 | return nullptr; 133 | } 134 | } 135 | return item; 136 | } 137 | 138 | //find lowest value in tree bigger than key. 139 | MapNode *upper_bound_(MapNode *current, MapNode *lowest, MapNode *bound) 140 | { 141 | if(!Comparator()(bound->key, current->key)) //!(bound->key < current->key) => bound->key >= current->key 142 | return lowest; 143 | if(Comparator()(current->key, lowest->key)) //current->key < lowest->key 144 | lowest = current; 145 | if(current->left) 146 | lowest = upper_bound_(current->left, lowest, bound); 147 | if(current->right) 148 | lowest = upper_bound_(current->right, lowest, bound); 149 | return lowest; 150 | } 151 | void clear_(MapNode *node) 152 | { 153 | if(!node) 154 | return; 155 | clear_(node->left); 156 | clear_(node->right); 157 | delete node; 158 | } 159 | public: 160 | 161 | Map() : head_(nullptr) 162 | { 163 | } 164 | 165 | ~Map() 166 | { 167 | clear(); 168 | } 169 | 170 | void clear() 171 | { 172 | clear_(head_); 173 | } 174 | 175 | iterator insert(const KeyType &key, const ValueType &value) 176 | { 177 | return insert_(key, value); 178 | } 179 | 180 | iterator insert(const KeyType &key, ValueType &&value) 181 | { 182 | return insert_(key, std::move(value)); 183 | } 184 | 185 | ValueType &operator [](const KeyType &key) 186 | { 187 | iterator it = find(key); 188 | if(it == end()) 189 | return insert(key, ValueType())->value; 190 | return it->value; 191 | } 192 | 193 | iterator upper_bound(const KeyType &key) 194 | { 195 | MapNode *node = find_(key); 196 | if(!node) 197 | return iterator(nullptr, this); 198 | if(!node->parent && !node->right) 199 | //this is root node and highest node 200 | return iterator(nullptr, this); 201 | 202 | if(node->right) //right node is always lower than parent node. 203 | return iterator(upper_bound_(node->right, node->right, node), this); 204 | 205 | MapNode *search = node->parent; 206 | while(search) 207 | { 208 | if(!Comparator()(search->key, node->key))//!(search->key < node->key) => search->key >= node->key 209 | return iterator(search, this); 210 | search = search->parent; 211 | } 212 | return iterator(nullptr, this); 213 | } 214 | 215 | iterator find(const KeyType &key) 216 | { 217 | return iterator(find_(key), this); 218 | } 219 | 220 | iterator end() 221 | { 222 | return iterator(nullptr, this); 223 | } 224 | 225 | iterator begin() 226 | { 227 | MapNode *item = head_; 228 | while(true) 229 | { 230 | if(item->left) 231 | item = item->left; 232 | else 233 | break; 234 | } 235 | return iterator(item, this); 236 | } 237 | }; 238 | -------------------------------------------------------------------------------- /Util/SharedPtr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace Impl 6 | { 7 | class RefCounter 8 | { 9 | private: 10 | size_t refCount_; 11 | public: 12 | RefCounter() : refCount_(0) {} 13 | 14 | void decRef() 15 | { 16 | refCount_ --; 17 | } 18 | 19 | void addRef() 20 | { 21 | refCount_ ++; 22 | } 23 | 24 | size_t refCount() 25 | { 26 | return refCount_; 27 | } 28 | }; 29 | 30 | class DeleterBase 31 | { 32 | public: 33 | virtual void execute(void *) = 0; 34 | }; 35 | 36 | template 37 | class Deleter : public DeleterBase 38 | { 39 | virtual void execute(void *ptr) 40 | { 41 | delete reinterpret_cast(ptr); 42 | } 43 | }; 44 | } 45 | 46 | template 47 | class SharedPtr 48 | { 49 | friend class SharedPtr; 50 | template 51 | friend class EnableSharedFromThis; 52 | private: 53 | PointerType *item_; 54 | Impl::RefCounter *refCounter_; 55 | Impl::DeleterBase *deleter_; 56 | SharedPtr(PointerType *item, Impl::RefCounter *refCounter, Impl::DeleterBase *deleter) : item_(nullptr), refCounter_(nullptr), deleter_(nullptr) 57 | { 58 | reset(item, refCounter, deleter); 59 | } 60 | 61 | void EnableShared(const void *) {} //not inherited 62 | 63 | template 64 | void EnableShared(EnableSharedPointerType *item, typename EnableSharedPointerType::_EnableSharedType * = nullptr) 65 | { 66 | item_->originalRefCounter_ = refCounter_; 67 | item_->originalDeleter_ = deleter_; 68 | } 69 | public: 70 | SharedPtr(PointerType *item) : item_(nullptr), refCounter_(nullptr), deleter_(nullptr) 71 | { 72 | if(!item) 73 | reset(nullptr, nullptr, nullptr); 74 | else 75 | reset(item, new Impl::RefCounter(), new Impl::Deleter()); 76 | } 77 | 78 | SharedPtr() : item_(nullptr), refCounter_(nullptr), deleter_(nullptr) {} 79 | 80 | SharedPtr(const SharedPtr &other) : item_(nullptr), refCounter_(nullptr), deleter_(nullptr) 81 | { 82 | reset(other.item_, other.refCounter_, other.deleter_); 83 | } 84 | 85 | template 86 | SharedPtr(const SharedPtr &other) : item_(nullptr), refCounter_(nullptr), deleter_(nullptr) 87 | { 88 | reset(static_cast(other.item_), other.refCounter_, other.deleter_); 89 | } 90 | 91 | SharedPtr(SharedPtr &&other) : item_(other.item_), refCounter_(other.refCounter_), deleter_(other.deleter_) 92 | { 93 | other.item_ = nullptr; 94 | other.refCounter_ = nullptr; 95 | other.deleter_ = nullptr; 96 | } 97 | 98 | template 99 | SharedPtr(SharedPtr &&other) : item_(static_cast(other.item_)), refCounter_(other.refCounter_), deleter_(other.deleter_) 100 | { 101 | other.item_ = nullptr; 102 | other.refCounter_ = nullptr; 103 | other.deleter_ = nullptr; 104 | } 105 | 106 | ~SharedPtr() 107 | { 108 | reset(nullptr, nullptr, nullptr); 109 | } 110 | 111 | const SharedPtr &operator =(const SharedPtr &other) 112 | { 113 | reset(other.item_, other.refCounter_, other.deleter_); 114 | return *this; 115 | } 116 | 117 | const SharedPtr &operator =(SharedPtr &&other) 118 | { 119 | item_ = other.item_; 120 | refCounter_ = other.refCounter_; 121 | deleter_ = other.deleter_; 122 | 123 | other.item_ = nullptr; 124 | other.refCounter_ = nullptr; 125 | other.deleter_ = nullptr; 126 | return *this; 127 | } 128 | 129 | void reset(PointerType *item = nullptr, Impl::RefCounter *refCounter = nullptr, Impl::DeleterBase *deleter = nullptr) 130 | { 131 | if(item_) 132 | { 133 | refCounter_->decRef(); 134 | if(refCounter_->refCount() == 0) 135 | { 136 | deleter_->execute(item_); 137 | delete deleter_; 138 | delete refCounter_; 139 | } 140 | } 141 | item_ = item; 142 | refCounter_ = refCounter; 143 | deleter_ = deleter; 144 | if(item_) 145 | { 146 | refCounter->addRef(); 147 | EnableShared(item); 148 | } 149 | } 150 | 151 | PointerType *operator ->() 152 | { 153 | return item_; 154 | } 155 | 156 | const PointerType * const operator ->() const 157 | { 158 | return item_; 159 | } 160 | 161 | PointerType *get() 162 | { 163 | return item_; 164 | } 165 | 166 | const PointerType *const get() const 167 | { 168 | return item_; 169 | } 170 | 171 | size_t getRef() 172 | { 173 | return refCounter_->refCount(); 174 | } 175 | 176 | bool operator !() const 177 | { 178 | return item_ == nullptr; 179 | } 180 | }; 181 | 182 | template 183 | class EnableSharedFromThis 184 | { 185 | template 186 | friend class SharedPtr; 187 | private: 188 | Impl::RefCounter *originalRefCounter_; 189 | Impl::DeleterBase *originalDeleter_; 190 | public: 191 | typedef PointerType _EnableSharedType; 192 | EnableSharedFromThis() : originalRefCounter_(nullptr), originalDeleter_(nullptr) {} 193 | 194 | SharedPtr sharedFromThis() 195 | { 196 | return SharedPtr(static_cast(this), originalRefCounter_, originalDeleter_); 197 | } 198 | }; 199 | 200 | //VC11 doesn't support variadic templates.. damn 201 | template 202 | SharedPtr MakeShared() 203 | { 204 | return SharedPtr(new PointerType()); 205 | } 206 | 207 | template 208 | SharedPtr MakeShared(T1 a1) 209 | { 210 | return SharedPtr(new PointerType(a1)); 211 | } 212 | 213 | template 214 | SharedPtr MakeShared(T1 a1, T2 a2) 215 | { 216 | return SharedPtr(new PointerType(a1, a2)); 217 | } 218 | 219 | template 220 | SharedPtr MakeShared(T1 a1, T2 a2, T3 a3) 221 | { 222 | return SharedPtr(new PointerType(a1, a2, a3)); 223 | } 224 | 225 | template 226 | SharedPtr MakeShared(T1 a1, T2 a2, T3 a3, T4 a4) 227 | { 228 | return SharedPtr(new PointerType(a1, a2, a3, a4)); 229 | } 230 | 231 | template 232 | SharedPtr MakeShared(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) 233 | { 234 | return SharedPtr(new PointerType(a1, a2, a3, a4, a5)); 235 | } 236 | 237 | template 238 | SharedPtr MakeShared(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) 239 | { 240 | return SharedPtr(new PointerType(a1, a2, a3, a4, a5, a6)); 241 | } -------------------------------------------------------------------------------- /Util/String.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "TypeTraits.h" 6 | #include "Vector.h" 7 | 8 | template 9 | class StringBase : private Vector 10 | { 11 | private: 12 | static size_t length_(const CharacterType *str) 13 | { 14 | size_t result = 0; 15 | while(*str ++) 16 | result ++; 17 | return result; 18 | } 19 | public: 20 | typedef typename Vector::iterator iterator; 21 | typedef typename Vector::const_iterator const_iterator; 22 | typedef CharacterType value_type; 23 | 24 | StringBase() 25 | { 26 | 27 | } 28 | 29 | StringBase(const CharacterType *string) 30 | { 31 | assign(string); 32 | } 33 | 34 | StringBase(StringBase &&operand) : Vector(std::move(operand)) {} 35 | StringBase(const StringBase &operand) : Vector(operand) {} 36 | 37 | template 38 | StringBase(IteratorType start, IteratorType end) 39 | { 40 | assign(start, end); 41 | } 42 | 43 | template 44 | void assign(IteratorType start, IteratorType end) 45 | { 46 | size_t length = end - start; 47 | Vector::resize(length + 1); 48 | 49 | size_t i = 0; 50 | for(IteratorType it = start; it != end; it ++, i ++) 51 | get()[i] = *it; 52 | get()[length] = 0; 53 | } 54 | 55 | void assign(const CharacterType *string) 56 | { 57 | size_t length = length_(string); 58 | if(length) 59 | { 60 | Vector::resize(length + 1); 61 | Vector::assign(const_cast(string), length + 1); 62 | } 63 | } 64 | 65 | void push_back(CharacterType item) 66 | { 67 | if(size()) 68 | Vector::insert(length(), item); 69 | else 70 | { 71 | Vector::push_back(item); 72 | Vector::push_back(0); 73 | } 74 | } 75 | 76 | void append(const StringBase &operand) 77 | { 78 | if(size()) 79 | { 80 | Vector::insert(length(), operand); 81 | Vector::resize(size() - 1); 82 | } 83 | else 84 | assign(operand.begin(), operand.end()); 85 | } 86 | 87 | CharacterType at(size_t pos) const 88 | { 89 | return get()[pos]; 90 | } 91 | 92 | CharacterType &operator [](size_t pos) const 93 | { 94 | return get()[pos]; 95 | } 96 | 97 | void resize(size_t size) 98 | { 99 | Vector::resize(size + 1); 100 | get()[size] = 0; 101 | } 102 | 103 | size_t length() const 104 | { 105 | size_t size = Vector::size(); 106 | return (size != 0 ? size - 1 : 0); 107 | } 108 | 109 | iterator begin() 110 | { 111 | return Vector::begin(); 112 | } 113 | 114 | iterator end() 115 | { 116 | return Vector::end(); 117 | } 118 | 119 | const_iterator begin() const 120 | { 121 | return Vector::begin(); 122 | } 123 | 124 | const_iterator end() const 125 | { 126 | return Vector::end(); 127 | } 128 | 129 | StringBase substr(size_t start, int len = -1) const 130 | { 131 | if(len == -1) 132 | len = length() - start; 133 | return StringBase(begin() + start, begin() + start + len); 134 | } 135 | 136 | const CharacterType *c_str() const 137 | { 138 | return const_cast(get()); 139 | } 140 | 141 | int find(CharacterType pattern, size_t start = 0) const 142 | { 143 | for(size_t i = start; i < length(); i ++) 144 | if(get()[i] == pattern) 145 | return i; 146 | return -1; 147 | } 148 | 149 | int rfind(CharacterType pattern, int start = -1) const 150 | { 151 | if(start == -1) 152 | start = length(); 153 | for(int i = start - 1; i >= 0; i --) 154 | if(get()[i] == pattern) 155 | return i; 156 | return -1; 157 | } 158 | 159 | int compare(const CharacterType *operand) const 160 | { 161 | if(!get()) 162 | return 1; 163 | size_t i; 164 | for(i = 0; operand[i] != 0 && get()[i] != 0; i ++) 165 | if(operand[i] != get()[i]) 166 | return get()[i] - operand[i]; 167 | return get()[i] - operand[i]; 168 | } 169 | 170 | int compare(const StringBase &operand) const 171 | { 172 | if(operand.size() > size()) 173 | return -1; 174 | else if(operand.size() < size()) 175 | return 1; 176 | return compare(operand.c_str()); 177 | } 178 | 179 | static CharacterType to_lower(CharacterType x) 180 | { 181 | return (x >= CharacterType('A') && x <= CharacterType('Z') ? x - (CharacterType('A') - CharacterType('a')) : x); 182 | } 183 | 184 | int icompare(const CharacterType *operand) const 185 | { 186 | if(!get()) 187 | return 1; 188 | size_t i; 189 | for(i = 0; operand[i] != 0 && get()[i] != 0; i ++) 190 | if(to_lower(operand[i]) != to_lower(get()[i])) 191 | return to_lower(get()[i]) - to_lower(operand[i]); 192 | return to_lower(get()[i]) - to_lower(operand[i]); 193 | } 194 | 195 | int icompare(const StringBase &operand) const 196 | { 197 | if(operand.size() > size()) 198 | return -1; 199 | else if(operand.size() < size()) 200 | return 1; 201 | return icompare(operand.c_str()); 202 | } 203 | 204 | bool operator ==(const StringBase &operand) const 205 | { 206 | return compare(operand.c_str()) == 0; 207 | } 208 | 209 | bool operator ==(const char *operand) const 210 | { 211 | return compare(operand) == 0; 212 | } 213 | 214 | const StringBase &operator =(const StringBase &operand) 215 | { 216 | Vector::operator =(operand); 217 | return *this; 218 | } 219 | 220 | const StringBase &operator =(StringBase &&operand) 221 | { 222 | Vector::operator =(std::move(operand)); 223 | return *this; 224 | } 225 | 226 | bool operator <(const StringBase &operand) const 227 | { 228 | return compare(operand.c_str()) < 0; 229 | } 230 | 231 | bool operator !=(const StringBase &operand) const 232 | { 233 | return compare(operand.c_str()) != 0; 234 | } 235 | 236 | StringBase operator +(CharacterType operand) const 237 | { 238 | String result(*this); 239 | result.push_back(operand); 240 | return result; 241 | } 242 | 243 | StringBase operator +(const StringBase &operand) const 244 | { 245 | StringBase result(*this); 246 | result.append(operand); 247 | return result; 248 | } 249 | }; 250 | 251 | typedef StringBase String; 252 | typedef StringBase WString; 253 | 254 | template 255 | class CaseInsensitiveStringComparator 256 | { 257 | public: 258 | bool operator ()(const ValueType &a, const ValueType &b) 259 | { 260 | return a.icompare(b) < 0; 261 | } 262 | }; 263 | 264 | inline String WStringToString(const WString &input) 265 | { 266 | String result; 267 | if(sizeof(wchar_t) == 2) 268 | { 269 | //utf16 270 | for(size_t i = 0; i < input.length();) 271 | { 272 | if(input[i] < 0xD800 || input[i] > 0xDFFF) 273 | { //no surrogate pair 274 | if(input[i] < 0x80) //1 byte 275 | { 276 | result.push_back((char)input[i]); 277 | } 278 | else if(input[i] < 0x800) 279 | { 280 | result.push_back((char)(0xC0 | ((input[i] & 0x7C0) >> 6))); 281 | result.push_back((char)(0x80 | (input[i] & 0x3F))); 282 | } 283 | else 284 | { 285 | result.push_back((char)(0xE0 | ((input[i] & 0xF000) >> 12))); 286 | result.push_back((char)(0x80 | ((input[i] & 0xFC0) >> 6))); 287 | result.push_back((char)(0x80 | (input[i] & 0x3F))); 288 | } 289 | } 290 | else 291 | { 292 | size_t temp; 293 | temp = (input[i] & 0x3FF << 10) | (input[i + 1] & 0x3FF); 294 | temp += 0x10000; 295 | if(temp < 0x80) //1 byte 296 | { 297 | result.push_back((char)temp); 298 | } 299 | else if(temp < 0x800) 300 | { 301 | result.push_back((char)(0xC0 | ((temp & 0x7C0) >> 6))); 302 | result.push_back((char)(0x80 | (temp & 0x3F))); 303 | } 304 | else if(temp < 0x10000) 305 | { 306 | result.push_back((char)(0xE0 | ((temp & 0xF000) >> 12))); 307 | result.push_back((char)(0x80 | ((temp & 0xFC0) >> 6))); 308 | result.push_back((char)(0x80 | (temp & 0x3F))); 309 | } 310 | else 311 | { 312 | result.push_back((char)(0xF0 | ((temp & 0x1C0000) >> 18))); 313 | result.push_back((char)(0x80 | ((temp & 0x3F000) >> 12))); 314 | result.push_back((char)(0x80 | ((temp & 0xFC0) >> 6))); 315 | result.push_back((char)(0x80 | (temp & 0x3F))); 316 | } 317 | i ++; 318 | } 319 | i ++; 320 | } 321 | } 322 | else if(sizeof(wchar_t) == 4) 323 | { 324 | //utf-32 325 | size_t i = 0; 326 | for(size_t i = 0; i < input.length();) 327 | { 328 | if(input[i] < 0x80) //1 byte 329 | { 330 | result.push_back((char)input[i]); 331 | } 332 | else if(input[i] < 0x800) 333 | { 334 | result.push_back((char)(0xC0 | ((input[i] & 0x7C0) >> 6))); 335 | result.push_back((char)(0x80 | (input[i] & 0x3F))); 336 | } 337 | else if(input[i] < 0x10000) 338 | { 339 | result.push_back((char)(0xE0 | ((input[i] & 0xF000) >> 12))); 340 | result.push_back((char)(0x80 | ((input[i] & 0xFC0) >> 6))); 341 | result.push_back((char)(0x80 | (input[i] & 0x3F))); 342 | } 343 | else 344 | { 345 | result.push_back((char)(0xF0 | ((input[i] & 0x1C0000) >> 18))); 346 | result.push_back((char)(0x80 | ((input[i] & 0x3F000) >> 12))); 347 | result.push_back((char)(0x80 | ((input[i] & 0xFC0) >> 6))); 348 | result.push_back((char)(0x80 | (input[i] & 0x3F))); 349 | } 350 | i ++; 351 | } 352 | } 353 | return result; 354 | } 355 | 356 | inline WString StringToWString(const String &input) 357 | { 358 | WString result; 359 | if(sizeof(wchar_t) == 2) 360 | { 361 | for(size_t i = 0; i < input.length();) 362 | { 363 | if(!((input[i] & 0xF0) == 0xF0)) 364 | { 365 | //1 utf-16 character 366 | if((input[i] & 0xE0) == 0xE0) 367 | { 368 | result.push_back(((input[i] & 0x0f) << 12) | (input[i + 1] & 0x3f) << 6 | (input[i + 2] & 0x3f)); 369 | i += 2; 370 | } 371 | else if((input[i] & 0xC0) == 0xC0) 372 | { 373 | result.push_back(((input[i] & 0x1f) << 6) | (input[i + 1] & 0x3f)); 374 | i ++; 375 | } 376 | else 377 | { 378 | result.push_back(input[i]); 379 | } 380 | } 381 | else 382 | { 383 | size_t temp = ((input[i] & 0x07) << 18) | ((input[i + 1] & 0x3f) << 12) | ((input[i + 2] & 0x3f) << 6) | (input[i + 3] & 0x3f); 384 | i += 3; 385 | temp -= 0x10000; 386 | result.push_back(0xD800 | (temp & 0xFFC00)); 387 | result.push_back(0xDC00 | (temp & 0x3FF)); 388 | } 389 | i ++; 390 | } 391 | } 392 | else if(sizeof(wchar_t) == 4) 393 | { 394 | for(size_t i = 0; i < input.length();) 395 | { 396 | if((input[i] & 0xF0) == 0xF0) 397 | { 398 | result.push_back(((input[i] & 0x07) << 18) | ((input[i + 1] & 0x3f) << 12) | ((input[i + 2] & 0x3f) << 6) | (input[i + 3] & 0x3f)); 399 | i += 3; 400 | } 401 | else if((input[i] & 0xE0) == 0xE0) 402 | { 403 | result.push_back(((input[i] & 0x0f) << 12) | ((input[i + 1] & 0x3f) << 6) | (input[i + 2] & 0x3f)); 404 | i += 2; 405 | } 406 | else if((input[i] & 0xC0) == 0xC0) 407 | { 408 | result.push_back(((input[i] & 0x1f) << 6) | (input[i + 1] & 0x3f)); 409 | i ++; 410 | } 411 | else 412 | { 413 | result.push_back(input[i]); 414 | } 415 | i ++; 416 | } 417 | } 418 | 419 | return result; 420 | } 421 | 422 | inline int StringToInt(const String &str) 423 | { 424 | int value = 0; 425 | size_t i = 0; 426 | if(str[0] == '-') 427 | i ++; 428 | for(; i < str.length(); i ++) 429 | { 430 | if(str[i] <= '9' && str[i] >= '0') 431 | { 432 | value *= 10; 433 | value += str[i] - '0'; 434 | } 435 | else 436 | break; 437 | } 438 | if(str[0] == '-') 439 | return -value; 440 | 441 | return value; 442 | } 443 | -------------------------------------------------------------------------------- /Util/TypeTraits.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef _MSC_VER 4 | #include //for std::move. Just including makes static data entry, So we can't. 5 | #endif 6 | -------------------------------------------------------------------------------- /Util/Util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | template 6 | typename IteratorType binarySearch(IteratorType begin, IteratorType end, Comparator comparator) 7 | { 8 | int s = 0; 9 | int e = end - begin; 10 | 11 | while(s <= e) 12 | { 13 | int m = (s + e) / 2; 14 | int cmp = comparator(begin + m); 15 | if(cmp > 0) 16 | e = m - 1; 17 | else if(cmp < 0) 18 | s = m + 1; 19 | else 20 | return begin + m; 21 | } 22 | return end; 23 | } 24 | 25 | template 26 | size_t makePattern(uint8_t val); 27 | 28 | template<> 29 | static size_t makePattern<4>(uint8_t val) 30 | { 31 | return (val << 24) | (val << 16) | (val << 8) | val; 32 | } 33 | 34 | template<> 35 | static size_t makePattern<8>(uint8_t val) 36 | { 37 | return ((uint64_t)val << 58) | ((uint64_t)val << 52) | ((uint64_t)val << 48) | ((uint64_t)val << 40) | ((uint64_t)val << 32) | (val << 24) | (val << 16) | (val << 8) | val;; 38 | } 39 | 40 | template 41 | static void setMemory(DestinationType *dest_, uint8_t val, size_t size) 42 | { 43 | uint8_t *dest = reinterpret_cast(dest_); 44 | if(!size) 45 | return; 46 | size_t i; 47 | 48 | for(i = 0; i < reinterpret_cast(dest) % sizeof(size_t); i ++) 49 | *(dest + i) = val; //align to boundary 50 | if(size > sizeof(size_t)) 51 | { 52 | size_t v = makePattern(val); 53 | for(; i <= size - sizeof(size_t); i += sizeof(size_t)) 54 | *reinterpret_cast(dest + i) = v; 55 | } 56 | for(; i < size; i ++) 57 | *(dest + i) = val; //remaining 58 | } 59 | 60 | template 61 | static void copyMemory(DestinationType *dest_, const SourceType *src_, size_t size) 62 | { 63 | uint8_t *dest = reinterpret_cast(dest_); 64 | const uint8_t *src = reinterpret_cast(src_); 65 | if(!size) 66 | return; 67 | size_t i; 68 | for(i = 0; i < reinterpret_cast(src) % sizeof(size_t); i ++) 69 | *(dest + i) = *(src + i); //align to boundary 70 | if(size > sizeof(size_t)) 71 | for(; i <= size - sizeof(size_t); i += sizeof(size_t)) 72 | *reinterpret_cast(dest + i) = *reinterpret_cast(src + i); 73 | for(; i < size; i ++) 74 | *(dest + i) = *(src + i); //remaining 75 | } 76 | 77 | template 78 | static void moveMemory(DestinationType *dest_, const SourceType *src_, size_t size) 79 | { 80 | uint8_t *dest = reinterpret_cast(dest_); 81 | const uint8_t *src = reinterpret_cast(src_); 82 | 83 | if(!size) 84 | return; 85 | 86 | if(dest <= src || dest >= src + size) //non-overlapping 87 | return copyMemory(dest_, src_, size); 88 | 89 | //overlapping, copy from higher address 90 | dest = dest + size - 1; 91 | src = src + size - 1; 92 | 93 | while(size--) 94 | { 95 | *dest = *src; 96 | dest --; 97 | src --; 98 | } 99 | } 100 | 101 | template 102 | static void zeroMemory(DestinationType *dest_, size_t size) 103 | { 104 | setMemory(dest_, 0, size); 105 | } 106 | 107 | static size_t multipleOf(size_t value, size_t n) 108 | { 109 | return ((value + n - 1) / n) * n; 110 | } 111 | 112 | static const uint8_t *decodeVarInt(const uint8_t *ptr, uint8_t *flag, uint32_t *size) 113 | { 114 | //f1xxxxxx 115 | //f01xxxxx xxxxxxxx 116 | //f001xxxx xxxxxxxx xxxxxxxx 117 | //f0001xxx xxxxxxxx xxxxxxxx xxxxxxxx 118 | //f0000100 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx 119 | *size = *ptr ++; 120 | *flag = (*size & 0x80) >> 7; 121 | if(*size & 0x40) 122 | *size &= 0x3f; 123 | else if(*size & 0x20) 124 | { 125 | *size &= 0x1f; 126 | *size <<= 8; 127 | *size |= *(ptr ++); 128 | } 129 | else if(*size & 0x10) 130 | { 131 | *size &= 0x0f; 132 | *size <<= 8; 133 | *size |= *(ptr ++); 134 | *size <<= 8; 135 | *size |= *(ptr ++); 136 | } 137 | else if(*size & 0x08) 138 | { 139 | *size &= 0x07; 140 | *size <<= 8; 141 | *size |= *(ptr ++); 142 | *size <<= 8; 143 | *size |= *(ptr ++); 144 | *size <<= 8; 145 | *size |= *(ptr ++); 146 | } 147 | else if(*size & 0x04) 148 | { 149 | *size = *(ptr ++); 150 | *size <<= 8; 151 | *size |= *(ptr ++); 152 | *size <<= 8; 153 | *size |= *(ptr ++); 154 | *size <<= 8; 155 | *size |= *(ptr ++); 156 | } 157 | 158 | return ptr; 159 | } 160 | 161 | static uint32_t simpleRLEDecompress(const uint8_t *compressedData, uint8_t *decompressedData) 162 | { 163 | uint32_t controlSize = *reinterpret_cast(compressedData); 164 | const uint8_t *data = compressedData + controlSize + 4; 165 | const uint8_t *control = compressedData + 4; 166 | const uint8_t *controlPtr = control; 167 | uint32_t resultSize = 0; 168 | 169 | uint8_t flag; 170 | size_t size; 171 | while(controlPtr < control + controlSize) 172 | { 173 | controlPtr = decodeVarInt(controlPtr, &flag, &size); 174 | resultSize += size; 175 | if(flag) 176 | { 177 | //succession 178 | for(; size > 0; size --) 179 | *decompressedData ++ = *data; 180 | data ++; 181 | } 182 | else 183 | { 184 | //nonsuccession 185 | for(; size > 0; size --) 186 | *decompressedData ++ = *data ++; 187 | } 188 | } 189 | 190 | return resultSize; 191 | } 192 | 193 | static uint32_t fnv1a(const uint8_t *data, size_t size) 194 | { 195 | uint32_t hash = 0x811c9dc5; 196 | for(size_t i = 0; i < size; i ++) 197 | { 198 | hash ^= data[i]; 199 | hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24); 200 | } 201 | return hash; 202 | } 203 | 204 | template 205 | uint32_t fnv1a(const T *data, size_t size) 206 | { 207 | return fnv1a(reinterpret_cast(data), size); 208 | } 209 | 210 | #define max(a, b) ((a) < (b) ? (b) : (a)) -------------------------------------------------------------------------------- /Util/Vector.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "TypeTraits.h" 5 | #include "Util.h" 6 | #include "SharedPtr.h" 7 | 8 | #include "DataSource.h" 9 | 10 | template 11 | class Vector 12 | { 13 | private: 14 | template 15 | struct VectorData : public DataSource, public EnableSharedFromThis> 16 | { 17 | size_t alloc; 18 | size_t size; 19 | ValueType *data; 20 | 21 | VectorData() : alloc(0), size(0), data(nullptr) 22 | { 23 | 24 | } 25 | 26 | virtual ~VectorData() 27 | { 28 | if(data) 29 | delete [] data; 30 | } 31 | 32 | virtual SharedPtr getView(uint64_t offset, size_t size) 33 | { 34 | return MakeShared(sharedFromThis(), offset, size); 35 | } 36 | 37 | virtual uint8_t *map(uint64_t offset) 38 | { 39 | return reinterpret_cast(data) + offset; 40 | } 41 | 42 | virtual void unmap() 43 | { 44 | 45 | } 46 | }; 47 | SharedPtr> data_; 48 | 49 | template 50 | static typename std::enable_if::value>::type 51 | _copyData(ValueType *target, ValueType *oldData, size_t size) 52 | { 53 | copyMemory(target, oldData, sizeof(value_type) * size); 54 | } 55 | 56 | template 57 | static typename std::enable_if::value>::type 58 | _copyData(ValueType *target, ValueType *oldData, size_t size) 59 | { 60 | for(size_t i = 0; i < size; i ++) 61 | target[i] = std::move(oldData[i]); 62 | } 63 | 64 | void resize_(uint32_t size, bool preserve) 65 | { 66 | if(data_->alloc <= size) 67 | { 68 | clone_(); 69 | data_->alloc *= 2; 70 | if(data_->alloc < size) 71 | data_->alloc = size + 10; 72 | ValueType *oldData = data_->data; 73 | data_->data = new ValueType[data_->alloc]; 74 | if(oldData) 75 | { 76 | if(preserve) 77 | _copyData(data_->data, oldData, data_->size); 78 | delete[] oldData; 79 | } 80 | } 81 | data_->size = size; 82 | } 83 | 84 | void clone_() 85 | { 86 | if(!data_) 87 | { 88 | data_ = new VectorData(); 89 | return; 90 | } 91 | if(data_.getRef() == 1) 92 | return; 93 | VectorData *newData = new VectorData(); 94 | newData->alloc = data_->alloc; 95 | newData->size = data_->size; 96 | newData->data = new ValueType[newData->alloc]; 97 | _copyData(newData->data, data_->data, data_->size); 98 | data_ = SharedPtr>(newData); 99 | } 100 | public: 101 | typedef ValueType value_type; 102 | typedef ValueType *iterator; 103 | typedef ValueType *const const_iterator; 104 | 105 | Vector() : data_(nullptr) 106 | { 107 | } 108 | 109 | Vector(uint32_t size) : data_(new VectorData()) 110 | { 111 | data_->size = size; 112 | data_->alloc = size; 113 | data_->data = new ValueType[size]; 114 | } 115 | 116 | ~Vector() 117 | { 118 | } 119 | 120 | Vector(const Vector &operand) : data_(operand.data_) 121 | { 122 | } 123 | 124 | Vector(Vector &&operand) : data_(std::move(operand.data_)) 125 | { 126 | } 127 | 128 | template 129 | Vector(IteratorType start, IteratorType end) : data_(new VectorData()) 130 | { 131 | assign(start, end); 132 | } 133 | 134 | const Vector &operator =(const Vector &operand) 135 | { 136 | data_ = operand.data_; 137 | return *this; 138 | } 139 | 140 | const Vector &operator =(Vector &&operand) 141 | { 142 | data_ = std::move(operand.data_); 143 | return *this; 144 | } 145 | 146 | ValueType *get() const 147 | { 148 | if(!data_) 149 | return nullptr; 150 | return data_->data; 151 | } 152 | 153 | void reserve(size_t size) 154 | { 155 | clone_(); 156 | size_t oldSize = data_->size; 157 | resize_(size, true); 158 | data_->size = oldSize; 159 | } 160 | 161 | void resize(size_t size) 162 | { 163 | clone_(); 164 | resize_(size, true); 165 | } 166 | 167 | void assign(ValueType *data, size_t size) 168 | { 169 | clone_(); 170 | resize_(size, false); 171 | for(size_t i = 0; i < size; i ++) 172 | data_->data[i] = data[i]; 173 | } 174 | 175 | template 176 | void assign(IteratorType start, IteratorType end) 177 | { 178 | clone_(); 179 | size_t length = end - start; 180 | resize_(length, false); 181 | 182 | size_t i = 0; 183 | for(IteratorType it = start; it != end; it ++, i ++) 184 | data_->data[i] = *it; 185 | } 186 | 187 | template 188 | void assign_move(IteratorType start, IteratorType end) 189 | { 190 | clone_(); 191 | size_t length = end - start; 192 | resize_(length, false); 193 | 194 | size_t i = 0; 195 | for(IteratorType it = start; it != end; it ++, i ++) 196 | data_->data[i] = std::move(*it); 197 | } 198 | 199 | iterator push_back(const ValueType &data) 200 | { 201 | clone_(); 202 | resize_(data_->size + 1, true); 203 | data_->data[data_->size - 1] = data; 204 | 205 | return &data_->data[data_->size - 1]; 206 | } 207 | 208 | iterator push_back(ValueType &&data) 209 | { 210 | clone_(); 211 | resize_(data_->size + 1, true); 212 | data_->data[data_->size - 1] = std::move(data); 213 | 214 | return &data_->data[data_->size - 1]; 215 | } 216 | 217 | void insert(size_t pos, const ValueType &data) 218 | { 219 | insert(pos, &data, 1); 220 | } 221 | 222 | void insert(size_t pos, const Vector &data) 223 | { 224 | insert(pos, data.get(), data.size()); 225 | } 226 | 227 | void insert(size_t pos, const value_type *data, size_t size) 228 | { 229 | clone_(); 230 | size_t originalSize = data_->size; 231 | resize_(data_->size + size, true); 232 | 233 | for(size_t i = originalSize + size - 1; i >= pos + size; i --) 234 | data_->data[i] = data_->data[i - size]; 235 | for(size_t i = 0; i < size; i ++) 236 | data_->data[i + pos] = data[i]; 237 | } 238 | 239 | void append(const Vector &data) 240 | { 241 | clone_(); 242 | insert(data_->size, data); 243 | } 244 | 245 | void append(const value_type *data, size_t size) 246 | { 247 | clone_(); 248 | insert(data_->size, data, size); 249 | } 250 | 251 | size_t size() const 252 | { 253 | if(!data_) 254 | return 0; 255 | return data_->size; 256 | } 257 | 258 | ValueType &operator[](uint32_t operand) 259 | { 260 | clone_(); 261 | return data_->data[operand]; 262 | } 263 | 264 | const ValueType &operator[](uint32_t operand) const 265 | { 266 | return data_->data[operand]; 267 | } 268 | 269 | iterator begin() 270 | { 271 | clone_(); 272 | return data_->data; 273 | } 274 | 275 | iterator end() 276 | { 277 | clone_(); 278 | return data_->data + data_->size; 279 | } 280 | 281 | const_iterator begin() const 282 | { 283 | return data_->data; 284 | } 285 | 286 | const_iterator end() const 287 | { 288 | return data_->data + data_->size; 289 | } 290 | 291 | SharedPtr getView(uint64_t offset, size_t size = 0) 292 | { 293 | clone_(); 294 | return data_->getView(offset, size); 295 | } 296 | 297 | SharedPtr asDataSource() 298 | { 299 | return data_; 300 | } 301 | }; 302 | -------------------------------------------------------------------------------- /Win32/MSVCHelper.cpp: -------------------------------------------------------------------------------- 1 | #include "../Util/Util.h" 2 | 3 | extern "C" void *__cdecl memset(void *, int, size_t); 4 | #pragma intrinsic(memset) 5 | extern "C" void *__cdecl memcpy(void *dst, const void *src, size_t size); 6 | #pragma intrinsic(memcpy) 7 | extern "C" void *__cdecl memmove(void *dst, const void *src, size_t size); 8 | 9 | extern "C" 10 | { 11 | int _purecall() 12 | { 13 | return 0; 14 | } 15 | 16 | #pragma function(memset) 17 | void *__cdecl memset(void *dst, int val, size_t size) 18 | { 19 | setMemory(dst, val, size); 20 | return dst; 21 | } 22 | 23 | #pragma function(memcpy) 24 | void *__cdecl memcpy(void *dst, const void *src, size_t size) 25 | { 26 | copyMemory(dst, src, size); 27 | return dst; 28 | } 29 | 30 | void *__cdecl memmove(void *dst, const void *src, size_t size) 31 | { 32 | moveMemory(dst, src, size); 33 | return dst; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Win32/Stub/Stage1/Stage1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../Win32Stub.h" 3 | #include "../../Win32Structure.h" 4 | #include "../../../Runtime/PEHeader.h" 5 | #include "../../../Util/Util.h" 6 | #include 7 | 8 | #pragma warning(disable:4733) //we don't use safeseh. 9 | 10 | #define STAGE2_SIZE 2097152 11 | 12 | uint8_t stage2[STAGE2_SIZE]; 13 | 14 | inline int unneededCopy(uint8_t *dst, const uint8_t *src) 15 | { 16 | for(size_t i = 0; i < 1000; i ++) 17 | dst[i] = src[i]; 18 | return src[0]; 19 | } 20 | 21 | int __stdcall Handler(EXCEPTION_RECORD *record, void *, CONTEXT *context, void*) 22 | { 23 | size_t temp; 24 | if(!context) 25 | return 0; 26 | if(context->Ecx == 0) 27 | { 28 | uint32_t sectionName = context->Edx; 29 | uint32_t stage2Data = context->Eax; 30 | uint32_t stage2Size = context->Ebx; 31 | _asm 32 | { 33 | sub esp, 14h 34 | mov ecx, cont 35 | mov [esp], ecx 36 | } 37 | if(reinterpret_cast(record->ExceptionAddress) == context->Eip) 38 | { 39 | Handler(record, 0, nullptr, 0); 40 | unneededCopy(stage2, reinterpret_cast(stage2Data)); 41 | } 42 | _asm 43 | { 44 | mov eax, [esp] 45 | retn 10h 46 | cont: 47 | mov ecx, temp 48 | lea ebx, dword ptr stage2 49 | mov edx, [stage2Data] 50 | mov ecx, [stage2Size] 51 | mov esi, [sectionName] 52 | mov [eax], ebx //re-trigger exception handler, start copy 53 | 54 | mov eax, fs:[0] //top level exception handler 55 | mov eax, [eax] //next exception handler 56 | mov fs:[0], eax //remove this exception handler 57 | } 58 | Win32StubStage2Header *header = reinterpret_cast(stage2); 59 | uint8_t *stage2Start = stage2 + sizeof(Win32StubStage2Header); 60 | if(header->magic != WIN32_STUB_STAGE2_MAGIC || buildSignature(stage2Start, header->imageSize) != header->signature) 61 | return ExceptionContinueSearch; 62 | 63 | //relocate 64 | uint64_t *relocationData = reinterpret_cast(stage2Start + header->imageSize); 65 | for(size_t i = 0; i < header->numberOfRelocations; ++ i) 66 | *reinterpret_cast(stage2Start + relocationData[i]) += -static_cast(header->originalBase) + reinterpret_cast(stage2Start); 67 | 68 | context->Eip = reinterpret_cast(stage2Start + header->entryPoint); 69 | return ExceptionContinueExecution; //continue to stage2 code 70 | } 71 | 72 | simpleDecrypt(context->Esi, reinterpret_cast(context->Edx), context->Ecx); 73 | simpleRLEDecompress(reinterpret_cast(context->Edx), reinterpret_cast(context->Ebx)); 74 | context->Eax = reinterpret_cast(&temp); //don't trigger exception again. 75 | return ExceptionContinueExecution; 76 | } 77 | 78 | int Entry() 79 | { 80 | __asm 81 | { 82 | push Handler 83 | push fs:[0] 84 | mov fs:[0], esp //set exception handler 85 | } 86 | 87 | uint32_t pebAddress = __readfsdword(0x30); 88 | PEB *peb = reinterpret_cast(pebAddress); 89 | LDR_MODULE *myModule = reinterpret_cast(peb->LoaderData->InLoadOrderModuleList.Flink); 90 | uint8_t *myBase = reinterpret_cast(myModule->BaseAddress); 91 | 92 | IMAGE_DOS_HEADER *dosHeader = reinterpret_cast(myBase); 93 | IMAGE_NT_HEADERS32 *ntHeader = reinterpret_cast(myBase + dosHeader->e_lfanew); 94 | IMAGE_SECTION_HEADER *sectionHeader = reinterpret_cast(myBase + dosHeader->e_lfanew + sizeof(uint32_t)+ sizeof(IMAGE_FILE_HEADER)+ ntHeader->FileHeader.SizeOfOptionalHeader); 95 | 96 | uint32_t sectionName = *reinterpret_cast(sectionHeader[2].Name); 97 | uint8_t *sectionData = reinterpret_cast(sectionHeader[2].VirtualAddress + reinterpret_cast(myBase)); 98 | 99 | size_t sectionSize = sectionHeader[2].VirtualSize; 100 | __asm 101 | { 102 | mov edx, sectionName 103 | mov eax, sectionData 104 | mov ebx, sectionSize 105 | xor ecx, ecx 106 | in eax, 4 107 | } 108 | } -------------------------------------------------------------------------------- /Win32/Stub/Stage1/Stage1.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15 | 16 | 17 | {A0359D6F-C025-4AA1-B44C-E5AB028BB89A} 18 | Win32Proj 19 | Stage1 20 | 21 | 22 | 23 | Application 24 | true 25 | v120 26 | Unicode 27 | 28 | 29 | Application 30 | false 31 | v120 32 | true 33 | Unicode 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | true 46 | false 47 | 48 | 49 | false 50 | false 51 | 52 | 53 | 54 | 55 | 56 | Level3 57 | Disabled 58 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 59 | false 60 | Default 61 | false 62 | ProgramDatabase 63 | false 64 | 65 | 66 | Windows 67 | false 68 | true 69 | Entry 70 | 0x00400000 71 | false 72 | true 73 | false 74 | 75 | 76 | 77 | 78 | Level3 79 | 80 | 81 | MaxSpeed 82 | true 83 | true 84 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 85 | false 86 | false 87 | None 88 | 89 | 90 | Windows 91 | false 92 | true 93 | true 94 | true 95 | Entry 96 | 0x00400000 97 | false 98 | true 99 | false 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /Win32/Stub/Stage1/Stage1.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;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /Win32/Stub/Stage2/Stage2.cpp: -------------------------------------------------------------------------------- 1 | #include "../../../Runtime/PEFormat.h" 2 | #include "../../Win32NativeHelper.h" 3 | #include "../../Win32SysCall.h" 4 | #include "../../../Util/DataSource.h" 5 | #include "../../Win32Loader.h" 6 | #include "../Win32Stub.h" 7 | 8 | uint8_t *mainData; 9 | uint8_t *impData; 10 | 11 | void Execute(); 12 | 13 | int Entry() 14 | { 15 | uint8_t *newLocation, *stage2Start; 16 | { 17 | Win32NativeHelper::get()->init(); 18 | 19 | Win32StubStage2Header *stage2Header; 20 | 21 | size_t myBase = Win32NativeHelper::get()->getMyBase(); 22 | PEFormat format; 23 | SharedPtr selfImageSource = MakeShared(reinterpret_cast(myBase), 0); 24 | format.load(selfImageSource, true); 25 | 26 | int cnt = 0; 27 | for(auto &i : format.getSections()) 28 | { 29 | if(cnt == 3) 30 | { 31 | mainData = new uint8_t[i.data->size()]; 32 | copyMemory(mainData, i.data->get(), i.data->size()); 33 | uint32_t seed = *reinterpret_cast(i.name.c_str()); 34 | simpleDecrypt(seed, mainData, i.data->size()); 35 | } 36 | else if(cnt == 4) 37 | { 38 | impData = new uint8_t[i.data->size()]; 39 | copyMemory(impData, i.data->get(), i.data->size()); 40 | uint32_t seed = *reinterpret_cast(i.name.c_str()); 41 | simpleDecrypt(seed, impData, i.data->size()); 42 | } 43 | else 44 | { 45 | size_t entryAddress = reinterpret_cast(Entry); 46 | if(i.baseAddress + myBase < entryAddress && entryAddress < i.baseAddress + i.size + myBase) 47 | stage2Header = reinterpret_cast(i.data->get()); 48 | } 49 | cnt ++; 50 | } 51 | 52 | //self relocation 53 | newLocation = reinterpret_cast(Win32SystemCaller::get()->allocateVirtual(0, stage2Header->imageSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)); 54 | stage2Start = reinterpret_cast(stage2Header) + sizeof(Win32StubStage2Header); 55 | copyMemory(newLocation, stage2Start, stage2Header->imageSize); 56 | uint64_t *relocationData = reinterpret_cast(stage2Start + stage2Header->imageSize); 57 | for(size_t i = 0; i < stage2Header->numberOfRelocations; ++ i) 58 | *reinterpret_cast(newLocation + relocationData[i]) += -reinterpret_cast(stage2Start) + reinterpret_cast(newLocation); 59 | } 60 | 61 | typedef void (*ExecuteType)(); 62 | ExecuteType executeFunction = reinterpret_cast(reinterpret_cast(Execute) - reinterpret_cast(stage2Start) + reinterpret_cast(newLocation)); 63 | executeFunction(); 64 | 65 | return 0; 66 | } 67 | 68 | void Execute() 69 | { 70 | Win32NativeHelper::get()->init(); 71 | Win32SystemCaller::get(true); 72 | Win32SystemCaller::get()->unmapViewOfSection(reinterpret_cast(Win32NativeHelper::get()->getMyBase())); 73 | 74 | Image mainImage = Image::unserialize(MakeShared(mainData)->getView(0), nullptr); 75 | 76 | List importImages; 77 | if(impData) 78 | { 79 | SharedPtr impDataSource = MakeShared(impData); 80 | uint32_t count = *reinterpret_cast(&impData[0]); 81 | size_t off = sizeof(count); 82 | size_t size = 0; 83 | 84 | for(size_t j = 0; j < count; ++ j) 85 | { 86 | importImages.push_back(Image::unserialize(impDataSource->getView(off), &size)); 87 | off += size; 88 | } 89 | } 90 | 91 | Win32Loader loader(std::move(mainImage), std::move(importImages)); 92 | loader.execute(); 93 | } -------------------------------------------------------------------------------- /Win32/Stub/Stage2/Stage2.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {EA3BC0AC-A01B-43E3-932C-B0F719BC57CC} 15 | Win32Proj 16 | Stage2 17 | 18 | 19 | 20 | Application 21 | true 22 | v120 23 | Unicode 24 | 25 | 26 | Application 27 | false 28 | v120 29 | true 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | false 45 | 46 | 47 | false 48 | false 49 | 50 | 51 | 52 | 53 | 54 | Level3 55 | Disabled 56 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 57 | false 58 | false 59 | Default 60 | false 61 | None 62 | false 63 | 64 | 65 | Windows 66 | false 67 | true 68 | Entry 69 | 70 | 71 | true 72 | false 73 | 74 | 75 | 76 | 77 | Level3 78 | 79 | 80 | Full 81 | true 82 | true 83 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 84 | false 85 | false 86 | false 87 | None 88 | true 89 | Size 90 | true 91 | 92 | 93 | Windows 94 | false 95 | true 96 | true 97 | true 98 | Entry 99 | 100 | 101 | true 102 | false 103 | UseLinkTimeCodeGeneration 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | false 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /Win32/Stub/Stage2/Stage2.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;mfcribbon-ms 15 | 16 | 17 | {4af6ca65-7552-4a74-97a6-6f7c02fe1bc4} 18 | 19 | 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 | LZMA 44 | 45 | 46 | LZMA 47 | 48 | 49 | LZMA 50 | 51 | 52 | Source Files 53 | 54 | 55 | Source Files 56 | 57 | 58 | 59 | 60 | LZMA 61 | 62 | 63 | LZMA 64 | 65 | 66 | LZMA 67 | 68 | 69 | LZMA 70 | 71 | 72 | LZMA 73 | 74 | 75 | -------------------------------------------------------------------------------- /Win32/Stub/Stubgen/Stubgen.cpp: -------------------------------------------------------------------------------- 1 | #include "../../Win32NativeHelper.h" 2 | #include "../../Win32File.h" 3 | #include "../../../Runtime/PEFormat.h" 4 | #include "../../../Util/Util.h" 5 | #include "../../../Util/Vector.h" 6 | 7 | #include "../Win32Stub.h" 8 | 9 | Vector encodeVarInt(uint8_t flag, uint32_t number) 10 | { 11 | //f1xxxxxx 12 | //f01xxxxx xxxxxxxx 13 | //f001xxxx xxxxxxxx xxxxxxxx 14 | //f0001xxx xxxxxxxx xxxxxxxx xxxxxxxx 15 | //f0000100 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx 16 | Vector result; 17 | if(number < 0x40) 18 | result.push_back((flag << 7) | 0x40 | number); 19 | else if(number < 0x2000) 20 | { 21 | result.push_back((flag << 7) | 0x20 | ((number & 0x1f00) >> 8)); 22 | result.push_back(number & 0xff); 23 | } 24 | else if(number < 0x100000) 25 | { 26 | result.push_back((flag << 7) | 0x10 | ((number & 0x0f0000) >> 16)); 27 | result.push_back((number >> 8) & 0xff); 28 | result.push_back(number & 0xff); 29 | } 30 | else if(number < 0x8000000) 31 | { 32 | result.push_back((flag << 7) | ((number & 0x07000000) >> 24)); 33 | result.push_back((number >> 16) & 0xff); 34 | result.push_back((number >> 8) & 0xff); 35 | result.push_back(number & 0xff); 36 | } 37 | else if(number < 0xFFFFFFFF) 38 | { 39 | result.push_back((flag << 7) | ((number & 0x07000000) >> 24)); 40 | result.push_back((number >> 24) & 0xff); 41 | result.push_back((number >> 16) & 0xff); 42 | result.push_back((number >> 8) & 0xff); 43 | result.push_back(number & 0xff); 44 | } 45 | return result; 46 | } 47 | 48 | Vector simpleRLECompress(const uint8_t *source, size_t size) 49 | { 50 | Vector control; 51 | Vector data; 52 | 53 | uint16_t lastData = 0x100; 54 | size_t successionCount = 1; 55 | size_t nonSuccessionCount = 0; 56 | 57 | for(size_t i = 0; i < size; ++ i) 58 | { 59 | if(source[i] == lastData) 60 | { 61 | if(nonSuccessionCount > 1) 62 | { 63 | control.append(encodeVarInt(0, nonSuccessionCount - 1)); 64 | successionCount = 1; 65 | nonSuccessionCount = 0; 66 | } 67 | successionCount ++; 68 | } 69 | 70 | if(source[i] != lastData) 71 | { 72 | if(successionCount > 1) 73 | { 74 | control.append(encodeVarInt(1, successionCount)); 75 | successionCount = 1; 76 | nonSuccessionCount = 0; 77 | } 78 | nonSuccessionCount ++; 79 | data.push_back(source[i]); 80 | } 81 | lastData = source[i]; 82 | } 83 | if(nonSuccessionCount > 1) 84 | control.append(encodeVarInt(0, nonSuccessionCount - 1)); 85 | if(successionCount > 1) 86 | control.append(encodeVarInt(1, successionCount)); 87 | 88 | Vector result(4); 89 | *reinterpret_cast(result.get()) = control.size(); 90 | result.append(control); 91 | result.append(data); 92 | 93 | return result; 94 | } 95 | 96 | void Entry() 97 | { 98 | Win32NativeHelper::get()->init(); 99 | 100 | List arguments = Win32NativeHelper::get()->getArgumentList(); 101 | 102 | if(arguments.size() < 4) 103 | return; 104 | 105 | auto &it = arguments.begin(); 106 | SharedPtr stage1 = MakeShared(*it ++); 107 | SharedPtr stage2 = MakeShared(*it ++); 108 | SharedPtr result = MakeShared(*it ++, true); 109 | 110 | PEFormat stage2Format; 111 | stage2Format.load(stage2, false); 112 | 113 | //serialize stage2 114 | size_t originalDataSize = sizeof(Win32StubStage2Header) + static_cast(stage2Format.getInfo().size) + stage2Format.getRelocations().size() * sizeof(uint64_t); 115 | Vector data(originalDataSize); 116 | Win32StubStage2Header *stage2Header = reinterpret_cast(data.get()); 117 | uint8_t *stage2Data = data.get() + sizeof(Win32StubStage2Header); 118 | uint64_t *relocationData = reinterpret_cast(data.get() + sizeof(Win32StubStage2Header) + stage2Format.getInfo().size); 119 | 120 | for(auto &i : stage2Format.getSections()) 121 | copyMemory(stage2Data + i.baseAddress, i.data->get(), i.data->size()); 122 | 123 | for(auto &i : stage2Format.getRelocations()) 124 | *relocationData ++ = i; 125 | 126 | stage2Header->magic = WIN32_STUB_STAGE2_MAGIC; 127 | stage2Header->imageSize = static_cast(stage2Format.getInfo().size); 128 | stage2Header->numberOfRelocations = stage2Format.getRelocations().size(); 129 | stage2Header->entryPoint = static_cast(stage2Format.getInfo().entryPoint); 130 | stage2Header->signature = buildSignature(stage2Data, stage2Header->imageSize); 131 | stage2Header->originalBase = static_cast(stage2Format.getInfo().baseAddress); 132 | 133 | SharedPtr> compressedStage2 = MakeShared>(simpleRLECompress(data.get(), data.size())); 134 | uint32_t seed = Win32NativeHelper::get()->getRandomValue(); 135 | simpleCrypt(seed, compressedStage2->get(), compressedStage2->size()); 136 | 137 | //create PE 138 | PEFormat resultFormat; 139 | resultFormat.load(stage1, false); 140 | List
resultSections(resultFormat.getSections()); 141 | 142 | size_t lastAddress = 0; 143 | Section stage2Section; 144 | stage2Section.baseAddress = 0; 145 | for(auto &i : resultSections) 146 | { 147 | if(i.data->size() == 0) //data 148 | i.flag |= SectionFlagExecute; 149 | lastAddress = static_cast(i.baseAddress + i.size); 150 | } 151 | if(stage2Section.baseAddress == 0) 152 | stage2Section.baseAddress = multipleOf(lastAddress, 0x1000); 153 | stage2Section.size = compressedStage2->size(); 154 | stage2Section.name.assign(reinterpret_cast(&seed), reinterpret_cast(&seed) + 4); 155 | stage2Section.flag = SectionFlagData | SectionFlagRead | SectionFlagWrite; 156 | stage2Section.data = compressedStage2->getView(0, compressedStage2->size()); 157 | resultSections.push_back(stage2Section); 158 | 159 | resultFormat.setSections(resultSections); 160 | 161 | size_t resultSize = resultFormat.estimateSize(); 162 | Vector resultData(resultSize); 163 | zeroMemory(resultData.get(), resultData.size()); 164 | resultFormat.save(resultData.asDataSource()); 165 | 166 | Vector compressedResult = simpleRLECompress(resultData.get(), resultSize); 167 | const char *hex = "0123456789ABCDEF"; 168 | 169 | result->write("#pragma once\n", 13); 170 | result->write("#include \n", 19); 171 | result->write("uint32_t win32StubSize = 0x", 27); 172 | 173 | result->write(&hex[(resultSize & 0xF0000000) >> 28], 1); 174 | result->write(&hex[(resultSize & 0x0F000000) >> 24], 1); 175 | result->write(&hex[(resultSize & 0x00F00000) >> 20], 1); 176 | result->write(&hex[(resultSize & 0x000F0000) >> 16], 1); 177 | result->write(&hex[(resultSize & 0x0000F000) >> 12], 1); 178 | result->write(&hex[(resultSize & 0x00000F00) >> 8], 1); 179 | result->write(&hex[(resultSize & 0x000000F0) >> 4], 1); 180 | result->write(&hex[resultSize & 0x0000000F], 1); 181 | result->write(";\n", 2); 182 | 183 | result->write("uint8_t win32StubData[] = {\n", 28); 184 | 185 | for(size_t i = 0; i < compressedResult.size(); ++ i) 186 | { 187 | result->write("0x", 2); 188 | result->write(&hex[(compressedResult[i] & 0xF0) >> 4], 1); 189 | result->write(&hex[compressedResult[i] & 0x0F], 1); 190 | result->write(", ", 2); 191 | 192 | if((i + 1) % 10 == 0 && i > 0) 193 | result->write("\n", 1); 194 | } 195 | result->write("};", 2); 196 | } 197 | -------------------------------------------------------------------------------- /Win32/Stub/Stubgen/Stubgen.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {DF6E3D45-C2BB-4E18-80AC-567DC2FF727D} 15 | Win32Proj 16 | Stubgen 17 | 18 | 19 | 20 | Application 21 | true 22 | v120 23 | Unicode 24 | 25 | 26 | Application 27 | false 28 | v120 29 | true 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | 45 | 46 | false 47 | 48 | 49 | 50 | 51 | 52 | Level3 53 | Disabled 54 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 55 | false 56 | Default 57 | false 58 | false 59 | 60 | 61 | Windows 62 | false 63 | true 64 | Entry 65 | 66 | 67 | 68 | 69 | Level3 70 | 71 | 72 | Full 73 | true 74 | true 75 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 76 | false 77 | false 78 | false 79 | true 80 | Size 81 | true 82 | 83 | 84 | Windows 85 | false 86 | true 87 | true 88 | true 89 | Entry 90 | UseLinkTimeCodeGeneration 91 | 92 | 93 | 94 | 95 | 96 | 97 | false 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /Win32/Stub/Stubgen/Stubgen.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;mfcribbon-ms 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 | -------------------------------------------------------------------------------- /Win32/Stub/Win32Stub.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WIN32_STUB_STAGE2_MAGIC 0xf00df00d 4 | 5 | struct Win32StubStage2Header 6 | { 7 | uint32_t magic; 8 | uint32_t signature; 9 | uint32_t imageSize; 10 | uint32_t numberOfRelocations; 11 | uint32_t entryPoint; 12 | uint32_t originalBase; 13 | }; 14 | 15 | inline uint32_t buildSignature(const uint8_t *data, size_t size) 16 | { 17 | uint32_t check = 0; 18 | for(size_t i = 0; i < size / 4; i ++) 19 | check += reinterpret_cast(data)[i]; 20 | return check; 21 | } 22 | 23 | inline void simpleCrypt(uint32_t seed, uint8_t *data, size_t size) 24 | { 25 | size_t i; 26 | for(i = 0; i < size - 4; i += 4) 27 | { 28 | reinterpret_cast(data)[i / 4] ^= seed; 29 | seed += reinterpret_cast(data)[i / 4]; 30 | seed = (seed >> 16) | (seed << 16); 31 | seed ^= reinterpret_cast(data)[i / 4]; 32 | } 33 | for(; i < size; i ++) 34 | data[i] ^= seed; 35 | } 36 | 37 | inline void simpleDecrypt(uint32_t seed, uint8_t *data, size_t size) 38 | { 39 | size_t i = 0; 40 | size_t lastData = reinterpret_cast(data)[i / 4]; 41 | 42 | reinterpret_cast(data)[i / 4] ^= seed; 43 | for(i = 4; i < size - 4; i += 4) 44 | { 45 | seed += lastData; 46 | seed = (seed >> 16) | (seed << 16); 47 | seed ^= lastData; 48 | lastData = reinterpret_cast(data)[i / 4]; 49 | reinterpret_cast(data)[i / 4] ^= seed; 50 | } 51 | seed += lastData; 52 | seed = (seed >> 16) | (seed << 16); 53 | seed ^= lastData; 54 | for(; i < size; i ++) 55 | data[i] ^= seed; 56 | } -------------------------------------------------------------------------------- /Win32/Win32File.cpp: -------------------------------------------------------------------------------- 1 | #include "Win32File.h" 2 | 3 | #include "../Util/Util.h" 4 | 5 | #include "Win32SysCall.h" 6 | #include "Win32NativeHelper.h" 7 | 8 | Win32File::Win32File(const String &filename, bool write) : mapCounter_(0), write_(write), mapHandle_(INVALID_HANDLE_VALUE) 9 | { 10 | open(filename); 11 | } 12 | 13 | Win32File::~Win32File() 14 | { 15 | close(); 16 | } 17 | 18 | void Win32File::open(const String &filename) 19 | { 20 | WString wFileName = StringToWString(filename); 21 | WString fullPath; 22 | 23 | if(wFileName[1] != L':') //relative 24 | { 25 | WString currentDirectory(Win32NativeHelper::get()->getCurrentDirectory()); 26 | 27 | fileName_ = filename; 28 | filePath_ = WStringToString(currentDirectory); 29 | fullPath = currentDirectory + wFileName; 30 | } 31 | else 32 | { 33 | int pathSeparatorPos = wFileName.rfind(L'\\'); 34 | WString path = wFileName.substr(0, pathSeparatorPos); 35 | WString fileName = wFileName.substr(pathSeparatorPos + 1); 36 | filePath_ = WStringToString(path); 37 | fileName_ = WStringToString(fileName); 38 | fullPath = wFileName; 39 | } 40 | 41 | int access = GENERIC_READ; 42 | int disposition = FILE_OPEN; 43 | 44 | if(write_) 45 | { 46 | access |= GENERIC_WRITE; 47 | disposition = FILE_OVERWRITE_IF; 48 | } 49 | 50 | fileHandle_ = Win32SystemCaller::get()->createFile(access, fullPath.c_str(), fullPath.length(), FILE_SHARE_READ, disposition); 51 | if(fileHandle_ == INVALID_HANDLE_VALUE) 52 | return; 53 | } 54 | 55 | void Win32File::resize(uint64_t newSize) 56 | { 57 | Win32SystemCaller::get()->setFileSize(fileHandle_, newSize); 58 | } 59 | 60 | void Win32File::close() 61 | { 62 | if(mapHandle_ != INVALID_HANDLE_VALUE) 63 | Win32SystemCaller::get()->closeHandle(mapHandle_); 64 | if(fileHandle_ != INVALID_HANDLE_VALUE) 65 | { 66 | Win32SystemCaller::get()->flushFile(fileHandle_); 67 | Win32SystemCaller::get()->closeHandle(fileHandle_); 68 | } 69 | } 70 | 71 | String Win32File::getFileName() 72 | { 73 | return fileName_; 74 | } 75 | 76 | String Win32File::getFilePath() 77 | { 78 | return filePath_; 79 | } 80 | 81 | void *Win32File::getHandle() 82 | { 83 | return fileHandle_; 84 | } 85 | 86 | void Win32File::write(const uint8_t *data, size_t size) 87 | { 88 | Win32SystemCaller::get()->writeFile(fileHandle_, data, size); 89 | } 90 | 91 | SharedPtr Win32File::getView(uint64_t offset, size_t size) 92 | { 93 | return MakeShared(sharedFromThis(), offset, size); 94 | } 95 | 96 | uint8_t *Win32File::map(uint64_t offset) 97 | { 98 | if(mapHandle_ == INVALID_HANDLE_VALUE) 99 | { 100 | int sectionProtect = PAGE_READONLY; 101 | if(write_) 102 | sectionProtect = PAGE_READWRITE; 103 | mapHandle_ = Win32SystemCaller::get()->createSection(fileHandle_, sectionProtect, 0, nullptr, 0); 104 | } 105 | 106 | if(mapCounter_ == 0) 107 | { 108 | uint32_t access = FILE_MAP_READ; 109 | if(write_) 110 | access = FILE_MAP_READ | FILE_MAP_WRITE; 111 | mapAddress_ = static_cast(Win32SystemCaller::get()->mapViewOfSection(mapHandle_, access, 0, 0, 0)); 112 | } 113 | 114 | mapCounter_ ++; 115 | return mapAddress_ + offset; 116 | } 117 | 118 | void Win32File::unmap() 119 | { 120 | mapCounter_ --; 121 | if(mapCounter_ == 0) 122 | { 123 | Win32SystemCaller::get()->unmapViewOfSection(mapAddress_); 124 | mapAddress_ = 0; 125 | } 126 | } 127 | 128 | String File::combinePath(const String &directory, const String &filename) 129 | { 130 | return directory + '\\' + filename; 131 | } 132 | 133 | bool File::isPathExists(const String &path) 134 | { 135 | WString widePath = StringToWString(path); 136 | if(Win32SystemCaller::get()->getFileAttributes(widePath.c_str(), widePath.length()) == INVALID_FILE_ATTRIBUTES) 137 | return false; 138 | return true; 139 | } 140 | 141 | SharedPtr File::open(const String &filename, bool write) 142 | { 143 | return MakeShared(filename, write); 144 | } 145 | -------------------------------------------------------------------------------- /Win32/Win32File.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Runtime/File.h" 4 | 5 | class Win32File : public File 6 | { 7 | friend class Win32FileView; 8 | private: 9 | void *fileHandle_; 10 | void *mapHandle_; 11 | uint8_t *mapAddress_; 12 | int mapCounter_; 13 | bool write_; 14 | void open(const String &filename); 15 | void close(); 16 | String fileName_; 17 | String filePath_; 18 | public: 19 | Win32File(const String &filename, bool write = false); 20 | virtual ~Win32File(); 21 | 22 | virtual String getFileName(); 23 | virtual String getFilePath(); 24 | virtual void *getHandle(); 25 | 26 | virtual SharedPtr getView(uint64_t offset, size_t size); 27 | virtual uint8_t *map(uint64_t offset); 28 | virtual void unmap(); 29 | virtual void write(const uint8_t *data, size_t size); 30 | virtual void resize(uint64_t newSize); 31 | }; 32 | -------------------------------------------------------------------------------- /Win32/Win32Loader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Util/Vector.h" 4 | #include "../Util/String.h" 5 | #include "../Util/List.h" 6 | #include "../Util/Map.h" 7 | #include "../Runtime/Image.h" 8 | 9 | struct _UNICODE_STRING; 10 | typedef _UNICODE_STRING UNICODE_STRING; 11 | 12 | struct _ANSI_STRING; 13 | typedef _ANSI_STRING ANSI_STRING; 14 | 15 | struct _IMAGE_DELAYLOAD_DESCRIPTOR; 16 | typedef _IMAGE_DELAYLOAD_DESCRIPTOR IMAGE_DELAYLOAD_DESCRIPTOR; 17 | typedef const IMAGE_DELAYLOAD_DESCRIPTOR *PCIMAGE_DELAYLOAD_DESCRIPTOR; 18 | class Win32Loader 19 | { 20 | private: 21 | Image image_; 22 | List imports_; 23 | List entryPointQueue_; 24 | Map loadedImages_; 25 | Map> loadedLibraries_; 26 | uint64_t loadLibrary(const String &filename, bool asDataFile = false); 27 | uint64_t getFunctionAddress(uint64_t library, const String &functionName, int ordinal = -1); 28 | uint64_t loadImage(Image &image, bool asDataFile = false); 29 | uint64_t mapImage(Image &image); 30 | void processImports(uint64_t baseAddress, const Image &image); 31 | void adjustPageProtection(uint64_t baseAddress, const Image &image); 32 | void executeEntryPoint(uint64_t baseAddress, const Image &image); 33 | void executeEntryPointQueue(); 34 | 35 | static uint32_t __stdcall GetModuleFileNameAProxy(void *hModule, char *lpFilename, uint32_t nSize); 36 | static uint32_t __stdcall GetModuleFileNameWProxy(void *hModule, wchar_t *lpFilename, uint32_t nSize); 37 | static void * __stdcall LoadLibraryAProxy(const char *libraryName); 38 | static void * __stdcall LoadLibraryWProxy(const wchar_t *libraryName); 39 | static void * __stdcall LoadLibraryExAProxy(const char *libraryName, void *, uint32_t); 40 | static void * __stdcall LoadLibraryExWProxy(const wchar_t *libraryName, void *, uint32_t flags); 41 | static void * __stdcall GetModuleHandleAProxy(const char *fileName); 42 | static void * __stdcall GetModuleHandleWProxy(const wchar_t *fileName); 43 | static uint32_t __stdcall GetModuleHandleExAProxy(uint32_t flags, const char *filename_, void **result); 44 | static uint32_t __stdcall GetModuleHandleExWProxy(uint32_t flags, const wchar_t *filename_, void **result); 45 | static void * __stdcall GetProcAddressProxy(void *library, char *functionName); 46 | static size_t __stdcall DisableThreadLibraryCallsProxy(void *module); 47 | static size_t __stdcall LdrAddRefDllProxy(size_t flags, void *library); 48 | static size_t __stdcall LdrLoadDllProxy(wchar_t *searchPath, size_t dllCharacteristics, UNICODE_STRING *dllName, void **baseAddress); 49 | static size_t __stdcall LdrResolveDelayLoadedAPIProxy(void *base, PCIMAGE_DELAYLOAD_DESCRIPTOR desc, void *dllhook, void *syshook, size_t *addr, size_t flags); 50 | static size_t __stdcall LdrGetDllHandleProxy(wchar_t *DllPath, size_t dllCharacteristics, UNICODE_STRING *dllName, void **dllHandle); 51 | static size_t __stdcall LdrGetDllHandleExProxy(size_t Flags, wchar_t *DllPath, size_t DllCharacteristics, UNICODE_STRING *DllName, void **DllHandle); 52 | static size_t __stdcall LdrGetProcedureAddressProxy(void *BaseAddress, ANSI_STRING *Name, size_t Ordinal, void **ProcedureAddress); 53 | 54 | template 55 | uint64_t matchApiSet(const String &filename, uint8_t *apiSetBase); 56 | public: 57 | Win32Loader(Image &&image, List &&imports); 58 | virtual ~Win32Loader() {} 59 | 60 | void execute(); 61 | }; -------------------------------------------------------------------------------- /Win32/Win32NativeHelper.cpp: -------------------------------------------------------------------------------- 1 | #include "Win32NativeHelper.h" 2 | 3 | #include 4 | 5 | #include "../Util/String.h" 6 | #include "../Runtime/Allocator.h" 7 | #include "Win32Structure.h" 8 | 9 | #include 10 | 11 | Win32NativeHelper *Win32NativeHelper::get() 12 | { 13 | static Win32NativeHelper helper; 14 | return &helper; 15 | } 16 | 17 | uint32_t Win32NativeHelper::getPEB64() 18 | { 19 | _asm 20 | { 21 | push 0x33 22 | push offset x64 23 | call fword ptr[esp] //jump to x64 mode 24 | add esp, 8 25 | jmp end 26 | x64: 27 | __asm __emit 0x65 __asm __emit 0x48 __asm __emit 0x8b __asm __emit 0x04 __asm __emit 0x25 __asm __emit 0x60 __asm __emit 0x00 __asm __emit 0x00 __asm __emit 0x00 28 | //mov rax, gs:[0x60] 29 | retf //return to x32 30 | end: 31 | } 32 | } 33 | 34 | void Win32NativeHelper::init() 35 | { 36 | myPEB_ = reinterpret_cast(__readfsdword(0x30)); 37 | myBase_ = reinterpret_cast(myPEB_->ImageBaseAddress); 38 | 39 | if(__readfsdword(0xC0) != 0) 40 | { 41 | isWoW64_ = true; 42 | myPEB64_ = reinterpret_cast(getPEB64()); 43 | } 44 | else 45 | { 46 | isWoW64_ = false; 47 | myPEB64_ = nullptr; 48 | } 49 | } 50 | 51 | size_t Win32NativeHelper::getMyBase() const 52 | { 53 | return myBase_; 54 | } 55 | 56 | void Win32NativeHelper::setMyBase(size_t address) 57 | { 58 | myBase_ = address; 59 | myPEB_->ImageBaseAddress = reinterpret_cast(address); 60 | if(isWoW64_) //we also have to modify 64bit peb if we are on wow64. 61 | myPEB64_->ImageBaseAddress = address; 62 | } 63 | 64 | wchar_t *Win32NativeHelper::getCommandLine() 65 | { 66 | return myPEB_->ProcessParameters->CommandLine.Buffer; 67 | } 68 | 69 | wchar_t *Win32NativeHelper::getCurrentDirectory() 70 | { 71 | return myPEB_->ProcessParameters->CurrentDirectoryPath.Buffer; 72 | } 73 | 74 | wchar_t *Win32NativeHelper::getEnvironments() 75 | { 76 | return reinterpret_cast(myPEB_->ProcessParameters->Environment); 77 | } 78 | 79 | uint8_t *Win32NativeHelper::getApiSet() 80 | { 81 | return myPEB_->ApiSet; 82 | } 83 | 84 | PEB *Win32NativeHelper::getPEB() 85 | { 86 | return myPEB_; 87 | } 88 | 89 | List Win32NativeHelper::getLoadedImages() 90 | { 91 | List result; 92 | LDR_MODULE *node = reinterpret_cast(getPEB()->LoaderData->InLoadOrderModuleList.Flink->Flink); 93 | while(node->BaseAddress) 94 | { 95 | Win32LoadedImage image; 96 | image.baseAddress = reinterpret_cast(node->BaseAddress); 97 | image.fileName = node->BaseDllName.Buffer; 98 | result.push_back(image); 99 | node = reinterpret_cast(node->InLoadOrderModuleList.Flink); 100 | } 101 | return result; 102 | } 103 | 104 | List Win32NativeHelper::getArgumentList() 105 | { 106 | String str = WStringToString(getCommandLine()); 107 | 108 | String item; 109 | List items; 110 | bool quote = false; 111 | bool slash = false; 112 | for(size_t i = 0; i < str.length(); i ++) 113 | { 114 | if(slash == false && quote == false && str[i] == '\"') 115 | { 116 | quote = true; 117 | continue; 118 | } 119 | if(slash == false && quote == true && str[i] == '\"') 120 | { 121 | quote = false; 122 | continue; 123 | } 124 | if(slash == true && quote == true && str[i] == '\"') 125 | { 126 | item.push_back('\"'); 127 | slash = false; 128 | continue; 129 | } 130 | if(slash == true && str[i] != '\"') 131 | { 132 | item.push_back('\\'); 133 | slash = false; 134 | } 135 | if(slash == false && str[i] == '\\') 136 | { 137 | slash = true; 138 | continue; 139 | } 140 | if(quote == false && str[i] == ' ') 141 | { 142 | if(item.length() == 0) 143 | continue; 144 | items.push_back(std::move(item)); 145 | item = ""; 146 | continue; 147 | } 148 | 149 | item.push_back(str[i]); 150 | } 151 | if(item.length()) 152 | items.push_back(std::move(item)); 153 | 154 | return items; 155 | } 156 | 157 | String Win32NativeHelper::getSystem32Directory() const 158 | { 159 | KUSER_SHARED_DATA *sharedData = reinterpret_cast(0x7ffe0000); 160 | 161 | String SystemRoot(WStringToString(sharedData->NtSystemRoot)); 162 | return SystemRoot + "\\System32"; 163 | } 164 | 165 | String Win32NativeHelper::getSysWOW64Directory() const 166 | { 167 | KUSER_SHARED_DATA *sharedData = reinterpret_cast(0x7ffe0000); 168 | 169 | String SystemRoot(WStringToString(sharedData->NtSystemRoot)); 170 | return SystemRoot + "\\SysWOW64"; 171 | } 172 | 173 | uint32_t Win32NativeHelper::getRandomValue() 174 | { 175 | KUSER_SHARED_DATA *sharedData = reinterpret_cast(0x7ffe0000); 176 | uint64_t tick = sharedData->TickCountQuad; 177 | uint32_t *temp = reinterpret_cast(&tick); 178 | return ((temp[0] | temp[1]) ^ 0xbeafdead) * temp[0]; 179 | } 180 | 181 | void Win32NativeHelper::showError(const String &message) 182 | { 183 | 184 | } 185 | 186 | bool Win32NativeHelper::isWoW64() 187 | { 188 | return isWoW64_; 189 | } 190 | 191 | void* operator new(size_t num) 192 | { 193 | return heapAlloc(num); 194 | } 195 | 196 | void* operator new[](size_t num) 197 | { 198 | return heapAlloc(num); 199 | } 200 | 201 | void operator delete(void *ptr) 202 | { 203 | heapFree(ptr); 204 | } 205 | 206 | void operator delete[](void *ptr) 207 | { 208 | heapFree(ptr); 209 | } 210 | -------------------------------------------------------------------------------- /Win32/Win32NativeHelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "../Util/List.h" 5 | #include "../Util/String.h" 6 | 7 | struct _PEB; 8 | typedef struct _PEB PEB; 9 | struct _PEB64; 10 | typedef struct _PEB64 PEB64; 11 | 12 | struct Win32LoadedImage 13 | { 14 | const wchar_t *fileName; 15 | uint64_t baseAddress; 16 | }; 17 | 18 | class Win32NativeHelper 19 | { 20 | private: 21 | PEB *myPEB_; 22 | PEB64 *myPEB64_; 23 | size_t myBase_; 24 | bool isWoW64_; 25 | 26 | uint32_t getPEB64(); 27 | void initHeap(); 28 | void initModuleList(); 29 | void relocateSelf(void *entry); 30 | public: 31 | void init(); 32 | uint8_t *getApiSet(); 33 | 34 | wchar_t *getCommandLine(); 35 | wchar_t *getCurrentDirectory(); 36 | wchar_t *getEnvironments(); 37 | PEB *getPEB(); 38 | List getLoadedImages(); 39 | List getArgumentList(); 40 | 41 | size_t getMyBase() const; 42 | void setMyBase(size_t address); 43 | 44 | String getSystem32Directory() const; 45 | String getSysWOW64Directory() const; 46 | 47 | bool isWoW64(); 48 | void showError(const String &message); 49 | 50 | uint32_t getRandomValue(); 51 | static Win32NativeHelper *get(); 52 | }; 53 | -------------------------------------------------------------------------------- /Win32/Win32Structure.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | //win32 structures 5 | 6 | typedef struct _UNICODE_STRING { 7 | uint16_t Length; 8 | uint16_t MaximumLength; 9 | wchar_t *Buffer; 10 | } UNICODE_STRING; 11 | typedef UNICODE_STRING *PUNICODE_STRING; 12 | typedef const UNICODE_STRING *PCUNICODE_STRING; 13 | 14 | typedef struct _ANSI_STRING { 15 | uint16_t Length; 16 | uint16_t MaximumLength; 17 | char * Buffer; 18 | } ANSI_STRING; 19 | typedef ANSI_STRING *PANSI_STRING; 20 | typedef const ANSI_STRING *PCANSI_STRING; 21 | 22 | typedef struct _OBJECT_ATTRIBUTES { 23 | uint32_t Length; 24 | void * RootDirectory; 25 | PUNICODE_STRING ObjectName; 26 | uint32_t Attributes; 27 | void * SecurityDescriptor; 28 | void * SecurityQualityOfService; 29 | } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; 30 | 31 | typedef struct _IO_STATUS_BLOCK 32 | { 33 | union 34 | { 35 | uint32_t Status; 36 | void * Pointer; 37 | }; 38 | uint32_t *Information; 39 | } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; 40 | 41 | #pragma pack(push, 8) 42 | typedef struct __declspec(align(8)) _UNICODE_STRING64 //to use 64bit UNICODE_STRING on 32bit. 43 | { 44 | union 45 | { 46 | struct 47 | { 48 | uint16_t Length; 49 | uint16_t MaximumLength; 50 | }; 51 | __declspec(align(8)) uint32_t LengthData; 52 | }; 53 | __declspec(align(8)) wchar_t *Buffer; 54 | } UNICODE_STRING64; 55 | typedef UNICODE_STRING64 *PUNICODE_STRING64; 56 | typedef const UNICODE_STRING64 *PCUNICODE_STRING64; 57 | 58 | typedef struct __declspec(align(8)) _OBJECT_ATTRIBUTES64 59 | { 60 | __declspec(align(8)) uint32_t Length; 61 | __declspec(align(8)) void * RootDirectory; 62 | __declspec(align(8)) PUNICODE_STRING64 ObjectName; 63 | __declspec(align(8)) uint32_t Attributes; 64 | __declspec(align(8)) void * SecurityDescriptor; 65 | __declspec(align(8)) void * SecurityQualityOfService; 66 | } OBJECT_ATTRIBUTES64, *POBJECT_ATTRIBUTES64; 67 | 68 | 69 | typedef struct __declspec(align(8)) _IO_STATUS_BLOCK64 70 | { 71 | union 72 | { 73 | __declspec(align(8)) uint64_t Status; 74 | __declspec(align(8)) void * Pointer; 75 | }; 76 | __declspec(align(8)) uint64_t *Information; 77 | } IO_STATUS_BLOCK64, *PIO_STATUS_BLOCK64; 78 | 79 | #pragma pack(pop, 8) 80 | 81 | typedef union _LARGE_INTEGER { 82 | struct { 83 | uint32_t LowPart; 84 | uint32_t HighPart; 85 | }; 86 | struct { 87 | uint32_t LowPart; 88 | uint32_t HighPart; 89 | } u; 90 | uint64_t QuadPart; 91 | } LARGE_INTEGER, *PLARGE_INTEGER; 92 | 93 | typedef struct _FILE_NETWORK_OPEN_INFORMATION { 94 | LARGE_INTEGER CreationTime; 95 | LARGE_INTEGER LastAccessTime; 96 | LARGE_INTEGER LastWriteTime; 97 | LARGE_INTEGER ChangeTime; 98 | LARGE_INTEGER AllocationSize; 99 | LARGE_INTEGER EndOfFile; 100 | uint32_t FileAttributes; 101 | } FILE_NETWORK_OPEN_INFORMATION, *PFILE_NETWORK_OPEN_INFORMATION; 102 | 103 | typedef struct _LIST_ENTRY { 104 | struct _LIST_ENTRY *Flink; 105 | struct _LIST_ENTRY *Blink; 106 | } LIST_ENTRY, *PLIST_ENTRY; 107 | 108 | typedef struct _LDR_MODULE { 109 | 110 | LIST_ENTRY InLoadOrderModuleList; 111 | LIST_ENTRY InMemoryOrderModuleList; 112 | LIST_ENTRY InInitializationOrderModuleList; 113 | void * BaseAddress; 114 | void * EntryPoint; 115 | uint32_t SizeOfImage; 116 | UNICODE_STRING FullDllName; 117 | UNICODE_STRING BaseDllName; 118 | uint32_t Flags; 119 | int16_t LoadCount; 120 | int16_t TlsIndex; 121 | LIST_ENTRY HashTableEntry; 122 | uint32_t TimeDateStamp; 123 | 124 | } LDR_MODULE, *PLDR_MODULE; 125 | 126 | typedef struct _PEB_LDR_DATA { 127 | 128 | uint32_t Length; 129 | int8_t Initialized; 130 | void * SsHandle; 131 | LIST_ENTRY InLoadOrderModuleList; 132 | LIST_ENTRY InMemoryOrderModuleList; 133 | LIST_ENTRY InInitializationOrderModuleList; 134 | 135 | } PEB_LDR_DATA, *PPEB_LDR_DATA; 136 | 137 | typedef struct _RTL_DRIVE_LETTER_CURDIR { 138 | 139 | uint16_t Flags; 140 | uint16_t Length; 141 | uint32_t TimeStamp; 142 | UNICODE_STRING DosPath; 143 | 144 | } RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR; 145 | 146 | typedef struct _RTL_USER_PROCESS_PARAMETERS { 147 | 148 | uint32_t MaximumLength; 149 | uint32_t Length; 150 | uint32_t Flags; 151 | uint32_t DebugFlags; 152 | void * ConsoleHandle; 153 | uint32_t ConsoleFlags; 154 | void * StdInputHandle; 155 | void * StdOutputHandle; 156 | void * StdErrorHandle; 157 | UNICODE_STRING CurrentDirectoryPath; 158 | void * CurrentDirectoryHandle; 159 | UNICODE_STRING DllPath; 160 | UNICODE_STRING ImagePathName; 161 | UNICODE_STRING CommandLine; 162 | void * Environment; 163 | uint32_t StartingPositionLeft; 164 | uint32_t StartingPositionTop; 165 | uint32_t Width; 166 | uint32_t Height; 167 | uint32_t CharWidth; 168 | uint32_t CharHeight; 169 | uint32_t ConsoleTextAttributes; 170 | uint32_t WindowFlags; 171 | uint32_t ShowWindowFlags; 172 | UNICODE_STRING WindowTitle; 173 | UNICODE_STRING DesktopName; 174 | UNICODE_STRING ShellInfo; 175 | UNICODE_STRING RuntimeData; 176 | RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20]; 177 | 178 | 179 | } RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; 180 | 181 | typedef void (*PPEBLOCKROUTINE)( 182 | void * PebLock 183 | ); 184 | 185 | struct API_SET_HOST { 186 | uint32_t ImportModuleName; 187 | uint16_t ImportModuleNameLength; 188 | uint32_t HostModuleName; 189 | uint16_t HostModuleNameLength; 190 | } ; 191 | 192 | struct API_SET_HOST_DESCRIPTOR { 193 | uint32_t NumberOfHosts; 194 | API_SET_HOST Hosts[1]; 195 | }; 196 | 197 | struct API_SET_ENTRY { 198 | uint32_t Name; 199 | uint16_t NameLength; 200 | uint32_t HostDescriptor; 201 | }; 202 | 203 | struct API_SET_HEADER { 204 | uint32_t Version; 205 | uint32_t NumberOfEntries; 206 | API_SET_ENTRY Entries[1]; 207 | }; 208 | 209 | struct API_SET_HOST2 210 | { 211 | uint32_t Unk1; 212 | uint32_t Unk2; 213 | uint32_t Unk3; 214 | uint32_t HostModuleName; 215 | uint32_t HostModuleNameLength; 216 | }; 217 | 218 | struct API_SET_HOST_DESCRIPTOR2 219 | { 220 | uint32_t Unk1; 221 | uint32_t NumberOfHosts; 222 | API_SET_HOST2 Hosts[1]; 223 | }; 224 | 225 | struct API_SET_ENTRY2 226 | { 227 | uint32_t Unk1; 228 | uint32_t Name; 229 | uint32_t NameLength; 230 | uint32_t Unk2; 231 | uint32_t Unk2Length; 232 | uint32_t HostDescriptor; 233 | }; 234 | 235 | struct API_SET_HEADER2 236 | { 237 | uint32_t Version; 238 | uint32_t Unk1; 239 | uint32_t Unk2; 240 | uint32_t NumberOfEntries; 241 | API_SET_ENTRY2 Entries[2]; 242 | }; 243 | 244 | 245 | typedef struct _PEB { 246 | 247 | int8_t InheritedAddressSpace; 248 | int8_t ReadImageFileExecOptions; 249 | int8_t BeingDebugged; 250 | int8_t Spare; 251 | void * Mutant; 252 | void * ImageBaseAddress; 253 | PPEB_LDR_DATA LoaderData; 254 | PRTL_USER_PROCESS_PARAMETERS ProcessParameters; 255 | void * SubSystemData; 256 | void * ProcessHeap; 257 | void * FastPebLock; 258 | PPEBLOCKROUTINE FastPebLockRoutine; 259 | PPEBLOCKROUTINE FastPebUnlockRoutine; 260 | uint32_t EnvironmentUpdateCount; 261 | void * KernelCallbackTable; 262 | void * EventLogSection; 263 | void * EventLog; 264 | uint8_t *ApiSet; 265 | uint32_t TlsExpansionCounter; 266 | void * TlsBitmap; 267 | uint32_t TlsBitmapBits[0x2]; 268 | void * ReadOnlySharedMemoryBase; 269 | void * ReadOnlySharedMemoryHeap; 270 | void * ReadOnlyStaticServerData; 271 | void * AnsiCodePageData; 272 | void * OemCodePageData; 273 | void * UnicodeCaseTableData; 274 | uint32_t NumberOfProcessors; 275 | uint32_t NtGlobalFlag; 276 | uint8_t Spare2[0x4]; 277 | LARGE_INTEGER CriticalSectionTimeout; 278 | uint32_t HeapSegmentReserve; 279 | uint32_t HeapSegmentCommit; 280 | uint32_t HeapDeCommitTotalFreeThreshold; 281 | uint32_t HeapDeCommitFreeBlockThreshold; 282 | uint32_t NumberOfHeaps; 283 | uint32_t MaximumNumberOfHeaps; 284 | void * *ProcessHeaps; 285 | void * GdiSharedHandleTable; 286 | void * ProcessStarterHelper; 287 | void * GdiDCAttributeList; 288 | void * LoaderLock; 289 | uint32_t OSMajorVersion; 290 | uint32_t OSMinorVersion; 291 | uint32_t OSBuildNumber; 292 | uint32_t OSPlatformId; 293 | uint32_t ImageSubSystem; 294 | uint32_t ImageSubSystemMajorVersion; 295 | uint32_t ImageSubSystemMinorVersion; 296 | uint32_t GdiHandleBuffer[0x22]; 297 | uint32_t PostProcessInitRoutine; 298 | uint32_t TlsExpansionBitmap; 299 | uint8_t TlsExpansionBitmapBits[0x80]; 300 | uint32_t SessionId; 301 | 302 | } PEB, *PPEB; 303 | 304 | 305 | typedef struct _PEB64 306 | { 307 | union 308 | { 309 | struct 310 | { 311 | int8_t InheritedAddressSpace; 312 | int8_t ReadImageFileExecOptions; 313 | int8_t BeingDebugged; 314 | int8_t Spare; 315 | }; 316 | uint64_t dummy; 317 | }; 318 | uint64_t Mutant; 319 | uint64_t ImageBaseAddress; 320 | } PEB64; 321 | 322 | #define DELETE (0x00010000L) 323 | #define READ_CONTROL (0x00020000L) 324 | #define WRITE_DAC (0x00040000L) 325 | #define WRITE_OWNER (0x00080000L) 326 | #define SYNCHRONIZE (0x00100000L) 327 | 328 | #define STANDARD_RIGHTS_REQUIRED (0x000F0000L) 329 | 330 | #define STANDARD_RIGHTS_READ (READ_CONTROL) 331 | #define STANDARD_RIGHTS_WRITE (READ_CONTROL) 332 | #define STANDARD_RIGHTS_EXECUTE (READ_CONTROL) 333 | 334 | #define STANDARD_RIGHTS_ALL (0x001F0000L) 335 | 336 | #define SPECIFIC_RIGHTS_ALL (0x0000FFFFL) 337 | 338 | 339 | #define FILE_READ_DATA ( 0x0001 ) // file & pipe 340 | #define FILE_LIST_DIRECTORY ( 0x0001 ) // directory 341 | 342 | #define FILE_WRITE_DATA ( 0x0002 ) // file & pipe 343 | #define FILE_ADD_FILE ( 0x0002 ) // directory 344 | 345 | #define FILE_APPEND_DATA ( 0x0004 ) // file 346 | #define FILE_ADD_SUBDIRECTORY ( 0x0004 ) // directory 347 | #define FILE_CREATE_PIPE_INSTANCE ( 0x0004 ) // named pipe 348 | 349 | 350 | #define FILE_READ_EA ( 0x0008 ) // file & directory 351 | 352 | #define FILE_WRITE_EA ( 0x0010 ) // file & directory 353 | 354 | #define FILE_EXECUTE ( 0x0020 ) // file 355 | #define FILE_TRAVERSE ( 0x0020 ) // directory 356 | 357 | #define FILE_DELETE_CHILD ( 0x0040 ) // directory 358 | 359 | #define FILE_READ_ATTRIBUTES ( 0x0080 ) // all 360 | 361 | #define FILE_WRITE_ATTRIBUTES ( 0x0100 ) // all 362 | 363 | #define FILE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF) 364 | 365 | #define FILE_GENERIC_READ (STANDARD_RIGHTS_READ |\ 366 | FILE_READ_DATA |\ 367 | FILE_READ_ATTRIBUTES |\ 368 | FILE_READ_EA |\ 369 | SYNCHRONIZE) 370 | 371 | 372 | #define FILE_GENERIC_WRITE (STANDARD_RIGHTS_WRITE |\ 373 | FILE_WRITE_DATA |\ 374 | FILE_WRITE_ATTRIBUTES |\ 375 | FILE_WRITE_EA |\ 376 | FILE_APPEND_DATA |\ 377 | SYNCHRONIZE) 378 | 379 | 380 | #define FILE_GENERIC_EXECUTE (STANDARD_RIGHTS_EXECUTE |\ 381 | FILE_READ_ATTRIBUTES |\ 382 | FILE_EXECUTE |\ 383 | SYNCHRONIZE) 384 | 385 | #define OBJ_INHERIT 0x00000002L 386 | #define OBJ_PERMANENT 0x00000010L 387 | #define OBJ_EXCLUSIVE 0x00000020L 388 | #define OBJ_CASE_INSENSITIVE 0x00000040L 389 | #define OBJ_OPENIF 0x00000080L 390 | #define OBJ_OPENLINK 0x00000100L 391 | #define OBJ_KERNEL_HANDLE 0x00000200L 392 | #define OBJ_FORCE_ACCESS_CHECK 0x00000400L 393 | #define OBJ_VALID_ATTRIBUTES 0x000007F2L 394 | 395 | 396 | #define EXCEPTION_MAXIMUM_PARAMETERS 15 // maximum number of exception parameters 397 | typedef struct _EXCEPTION_RECORD { 398 | uint32_t ExceptionCode; 399 | uint32_t ExceptionFlags; 400 | struct _EXCEPTION_RECORD *ExceptionRecord; 401 | void *ExceptionAddress; 402 | uint32_t NumberParameters; 403 | size_t *ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; 404 | } EXCEPTION_RECORD; 405 | 406 | 407 | #define SIZE_OF_80387_REGISTERS 80 408 | typedef struct _FLOATING_SAVE_AREA { 409 | uint32_t ControlWord; 410 | uint32_t StatusWord; 411 | uint32_t TagWord; 412 | uint32_t ErrorOffset; 413 | uint32_t ErrorSelector; 414 | uint32_t DataOffset; 415 | uint32_t DataSelector; 416 | uint8_t RegisterArea[SIZE_OF_80387_REGISTERS]; 417 | uint32_t Cr0NpxState; 418 | } FLOATING_SAVE_AREA; 419 | 420 | 421 | #define MAXIMUM_SUPPORTED_EXTENSION 512 422 | typedef struct _CONTEXT { 423 | 424 | // 425 | // The flags values within this flag control the contents of 426 | // a CONTEXT record. 427 | // 428 | // If the context record is used as an input parameter, then 429 | // for each portion of the context record controlled by a flag 430 | // whose value is set, it is assumed that that portion of the 431 | // context record contains valid context. If the context record 432 | // is being used to modify a threads context, then only that 433 | // portion of the threads context will be modified. 434 | // 435 | // If the context record is used as an IN OUT parameter to capture 436 | // the context of a thread, then only those portions of the thread's 437 | // context corresponding to set flags will be returned. 438 | // 439 | // The context record is never used as an OUT only parameter. 440 | // 441 | 442 | uint32_t ContextFlags; 443 | 444 | // 445 | // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is 446 | // set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT 447 | // included in CONTEXT_FULL. 448 | // 449 | 450 | uint32_t Dr0; 451 | uint32_t Dr1; 452 | uint32_t Dr2; 453 | uint32_t Dr3; 454 | uint32_t Dr6; 455 | uint32_t Dr7; 456 | 457 | // 458 | // This section is specified/returned if the 459 | // ContextFlags word contians the flag CONTEXT_FLOATING_POINT. 460 | // 461 | 462 | FLOATING_SAVE_AREA FloatSave; 463 | 464 | // 465 | // This section is specified/returned if the 466 | // ContextFlags word contians the flag CONTEXT_SEGMENTS. 467 | // 468 | 469 | uint32_t SegGs; 470 | uint32_t SegFs; 471 | uint32_t SegEs; 472 | uint32_t SegDs; 473 | 474 | // 475 | // This section is specified/returned if the 476 | // ContextFlags word contians the flag CONTEXT_INTEGER. 477 | // 478 | 479 | uint32_t Edi; 480 | uint32_t Esi; 481 | uint32_t Ebx; 482 | uint32_t Edx; 483 | uint32_t Ecx; 484 | uint32_t Eax; 485 | 486 | // 487 | // This section is specified/returned if the 488 | // ContextFlags word contians the flag CONTEXT_CONTROL. 489 | // 490 | 491 | uint32_t Ebp; 492 | uint32_t Eip; 493 | uint32_t SegCs; // MUST BE SANITIZED 494 | uint32_t EFlags; // MUST BE SANITIZED 495 | uint32_t Esp; 496 | uint32_t SegSs; 497 | 498 | // 499 | // This section is specified/returned if the ContextFlags word 500 | // contains the flag CONTEXT_EXTENDED_REGISTERS. 501 | // The format and contexts are processor specific 502 | // 503 | 504 | uint8_t ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION]; 505 | 506 | } CONTEXT; 507 | 508 | 509 | typedef enum _EXCEPTION_DISPOSITION { 510 | ExceptionContinueExecution, 511 | ExceptionContinueSearch, 512 | ExceptionNestedException, 513 | ExceptionCollidedUnwind 514 | } EXCEPTION_DISPOSITION; 515 | 516 | typedef struct _KSYSTEM_TIME 517 | { 518 | uint32_t LowPart; 519 | int32_t High1Time; 520 | int32_t High2Time; 521 | } KSYSTEM_TIME, *PKSYSTEM_TIME; 522 | 523 | typedef enum _ALTERNATIVE_ARCHITECTURE_TYPE 524 | { 525 | StandardDesign = 0, 526 | NEC98x86 = 1, 527 | EndAlternatives = 2 528 | } ALTERNATIVE_ARCHITECTURE_TYPE; 529 | 530 | typedef enum _NT_PRODUCT_TYPE 531 | { 532 | NtProductWinNt = 1, 533 | NtProductLanManNt = 2, 534 | NtProductServer = 3 535 | } NT_PRODUCT_TYPE; 536 | 537 | typedef struct _KUSER_SHARED_DATA 538 | { 539 | uint32_t TickCountLowDeprecated; 540 | uint32_t TickCountMultiplier; 541 | KSYSTEM_TIME InterruptTime; 542 | KSYSTEM_TIME SystemTime; 543 | KSYSTEM_TIME TimeZoneBias; 544 | uint16_t ImageNumberLow; 545 | uint16_t ImageNumberHigh; 546 | wchar_t NtSystemRoot[260]; 547 | uint32_t MaxStackTraceDepth; 548 | uint32_t CryptoExponent; 549 | uint32_t TimeZoneId; 550 | uint32_t LargePageMinimum; 551 | uint32_t Reserved2[7]; 552 | NT_PRODUCT_TYPE NtProductType; 553 | uint8_t ProductTypeIsValid; 554 | uint32_t NtMajorVersion; 555 | uint32_t NtMinorVersion; 556 | uint8_t ProcessorFeatures[64]; 557 | uint32_t Reserved1; 558 | uint32_t Reserved3; 559 | uint32_t TimeSlip; 560 | ALTERNATIVE_ARCHITECTURE_TYPE AlternativeArchitecture; 561 | LARGE_INTEGER SystemExpirationDate; 562 | uint32_t SuiteMask; 563 | uint8_t KdDebuggerEnabled; 564 | uint8_t NXSupportPolicy; 565 | uint32_t ActiveConsoleId; 566 | uint32_t DismountCount; 567 | uint32_t ComPlusPackage; 568 | uint32_t LastSystemRITEventTickCount; 569 | uint32_t NumberOfPhysicalPages; 570 | uint8_t SafeBootMode; 571 | uint32_t SharedDataFlags; 572 | uint32_t DbgErrorPortPresent: 1; 573 | uint32_t DbgElevationEnabled: 1; 574 | uint32_t DbgVirtEnabled: 1; 575 | uint32_t DbgInstallerDetectEnabled: 1; 576 | uint32_t SystemDllRelocated: 1; 577 | uint32_t SpareBits: 27; 578 | uint64_t TestRetInstruction; 579 | uint32_t SystemCall; 580 | uint32_t SystemCallReturn; 581 | uint64_t SystemCallPad[3]; 582 | union 583 | { 584 | KSYSTEM_TIME TickCount; 585 | uint64_t TickCountQuad; 586 | }; 587 | uint32_t Cookie; 588 | int64_t ConsoleSessionForegroundProcessId; 589 | uint32_t Wow64SharedInformation[16]; 590 | uint16_t UserModeGlobalLogger[8]; 591 | uint32_t HeapTracingPid[2]; 592 | uint32_t CritSecTracingPid[2]; 593 | uint32_t ImageFileExecutionOptions; 594 | union 595 | { 596 | uint64_t AffinityPad; 597 | uint32_t ActiveProcessorAffinity; 598 | }; 599 | uint64_t InterruptTimeBias; 600 | } KUSER_SHARED_DATA, *PKUSER_SHARED_DATA; 601 | 602 | -------------------------------------------------------------------------------- /Win32/Win32SysCall.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | enum Win32SystemCall 6 | { 7 | NtAllocateVirtualMemory, 8 | NtFreeVirtualMemory, 9 | NtProtectVirtualMemory, 10 | NtCreateFile, 11 | NtWriteFile, 12 | NtClose, 13 | NtCreateSection, 14 | NtMapViewOfSection, 15 | NtUnmapViewOfSection, 16 | NtQueryFullAttributesFile, 17 | NtSetInformationFile, 18 | NtFlushBuffersFile, 19 | NtFlushInstructionCache, 20 | NtTerminateProcess, 21 | 22 | SystemCallMax 23 | }; 24 | 25 | class Win32SystemCaller 26 | { 27 | protected: 28 | const uint16_t *systemCalls_; 29 | protected: 30 | Win32SystemCaller(const uint16_t *systemCalls) : systemCalls_(systemCalls) {} 31 | static uint32_t __cdecl executeWin32Syscall(uint32_t syscallno, uint32_t *argv); 32 | static uint32_t __cdecl executeWoW64Syscall(uint32_t syscallno, uint64_t *argv); 33 | public: 34 | virtual bool freeVirtual(void *BaseAddress) = 0; 35 | virtual void *allocateVirtual(size_t DesiredAddress, size_t RegionSize, size_t AllocationType, size_t Protect) = 0; 36 | virtual void protectVirtual(void *BaseAddress, size_t NumberOfBytes, size_t NewAccessProtection, size_t *OldAccessProtection = nullptr) = 0; 37 | virtual void *createFile(uint32_t DesiredAccess, const wchar_t *Filename, size_t FilenameLength, size_t ShareAccess, size_t CreateDisposition) = 0; 38 | virtual size_t writeFile(void *fileHandle, const uint8_t *buffer, size_t bufferSize) = 0; 39 | virtual void flushFile(void *fileHandle) = 0; 40 | virtual void closeHandle(void *handle) = 0; 41 | virtual void *createSection(void *file, uint32_t flProtect, uint64_t sectionSize, wchar_t *lpName, size_t NameLength) = 0; 42 | virtual void *mapViewOfSection(void *section, uint32_t dwDesiredAccess, uint64_t offset, size_t dwNumberOfBytesToMap, size_t lpBaseAddress) = 0; 43 | virtual void unmapViewOfSection(void *lpBaseAddress) = 0; 44 | virtual uint32_t getFileAttributes(const wchar_t *filePath, size_t filePathLen) = 0; 45 | virtual void setFileSize(void *file, uint64_t size) = 0; 46 | virtual void flushInstructionCache(size_t offset, size_t size) = 0; 47 | virtual void terminate() = 0; 48 | 49 | static Win32SystemCaller *get(bool forceinit = false); 50 | }; 51 | 52 | class Win32x86SystemCaller : public Win32SystemCaller 53 | { 54 | public: 55 | Win32x86SystemCaller(const uint16_t *systemCalls) : Win32SystemCaller(systemCalls) {} 56 | 57 | virtual bool freeVirtual(void *BaseAddress); 58 | virtual void *allocateVirtual(size_t DesiredAddress, size_t RegionSize, size_t AllocationType, size_t Protect); 59 | virtual void protectVirtual(void *BaseAddress, size_t NumberOfBytes, size_t NewAccessProtection, size_t *OldAccessProtection = nullptr); 60 | virtual void *createFile(uint32_t DesiredAccess, const wchar_t *Filename, size_t FilenameLength, size_t ShareAccess, size_t CreateDisposition); 61 | virtual size_t writeFile(void *fileHandle, const uint8_t *buffer, size_t bufferSize); 62 | virtual void flushFile(void *fileHandle); 63 | virtual void closeHandle(void *handle); 64 | virtual void *createSection(void *file, uint32_t flProtect, uint64_t sectionSize, wchar_t *lpName, size_t NameLength); 65 | virtual void *mapViewOfSection(void *section, uint32_t dwDesiredAccess, uint64_t offset, size_t dwNumberOfBytesToMap, size_t lpBaseAddress); 66 | virtual void unmapViewOfSection(void *lpBaseAddress); 67 | virtual uint32_t getFileAttributes(const wchar_t *filePath, size_t filePathLen); 68 | virtual void setFileSize(void *file, uint64_t size); 69 | virtual void flushInstructionCache(size_t offset, size_t size); 70 | virtual void terminate(); 71 | }; 72 | 73 | class Win32WOW64SystemCaller : public Win32SystemCaller 74 | { 75 | public: 76 | Win32WOW64SystemCaller(const uint16_t *systemCalls) : Win32SystemCaller(systemCalls) {} 77 | 78 | virtual bool freeVirtual(void *BaseAddress); 79 | virtual void *allocateVirtual(size_t DesiredAddress, size_t RegionSize, size_t AllocationType, size_t Protect); 80 | virtual void protectVirtual(void *BaseAddress, size_t NumberOfBytes, size_t NewAccessProtection, size_t *OldAccessProtection = nullptr); 81 | virtual void *createFile(uint32_t DesiredAccess, const wchar_t *Filename, size_t FilenameLength, size_t ShareAccess, size_t CreateDisposition); 82 | virtual size_t writeFile(void *fileHandle, const uint8_t *buffer, size_t bufferSize); 83 | virtual void flushFile(void *fileHandle); 84 | virtual void closeHandle(void *handle); 85 | virtual void *createSection(void *file, uint32_t flProtect, uint64_t sectionSize, wchar_t *lpName, size_t NameLength); 86 | virtual void *mapViewOfSection(void *section, uint32_t dwDesiredAccess, uint64_t offset, size_t dwNumberOfBytesToMap, size_t lpBaseAddress); 87 | virtual void unmapViewOfSection(void *lpBaseAddress); 88 | virtual uint32_t getFileAttributes(const wchar_t *filePath, size_t filePathLen); 89 | virtual void setFileSize(void *file, uint64_t size); 90 | virtual void flushInstructionCache(size_t offset, size_t size); 91 | virtual void terminate(); 92 | }; 93 | 94 | 95 | #define GENERIC_READ (0x80000000L) 96 | #define GENERIC_WRITE (0x40000000L) 97 | #define GENERIC_EXECUTE (0x20000000L) 98 | #define GENERIC_ALL (0x10000000L) 99 | 100 | #define FILE_SHARE_READ 0x00000001 101 | #define FILE_SHARE_WRITE 0x00000002 102 | #define FILE_SHARE_DELETE 0x00000004 103 | 104 | #define FILE_SUPERSEDE 0x00000000 105 | #define FILE_OPEN 0x00000001 106 | #define FILE_CREATE 0x00000002 107 | #define FILE_OPEN_IF 0x00000003 108 | #define FILE_OVERWRITE 0x00000004 109 | #define FILE_OVERWRITE_IF 0x00000005 110 | #define FILE_MAXIMUM_DISPOSITION 0x00000005 111 | 112 | #define PAGE_NOACCESS 0x01 113 | #define PAGE_READONLY 0x02 114 | #define PAGE_READWRITE 0x04 115 | #define PAGE_WRITECOPY 0x08 116 | #define PAGE_EXECUTE 0x10 117 | #define PAGE_EXECUTE_READ 0x20 118 | #define PAGE_EXECUTE_READWRITE 0x40 119 | #define PAGE_EXECUTE_WRITECOPY 0x80 120 | 121 | #define INVALID_HANDLE_VALUE reinterpret_cast(-1) 122 | 123 | #define SECTION_QUERY 0x0001 124 | #define SECTION_MAP_WRITE 0x0002 125 | #define SECTION_MAP_READ 0x0004 126 | #define SECTION_MAP_EXECUTE 0x0008 127 | #define SECTION_EXTEND_SIZE 0x0010 128 | #define SECTION_MAP_EXECUTE_EXPLICIT 0x0020 // not included in SECTION_ALL_ACCESS 129 | 130 | #define SECTION_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SECTION_QUERY|\ 131 | SECTION_MAP_WRITE | \ 132 | SECTION_MAP_READ | \ 133 | SECTION_MAP_EXECUTE | \ 134 | SECTION_EXTEND_SIZE) 135 | 136 | #define SESSION_QUERY_ACCESS 0x0001 137 | #define SESSION_MODIFY_ACCESS 0x0002 138 | 139 | #define SESSION_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | \ 140 | SESSION_QUERY_ACCESS | \ 141 | SESSION_MODIFY_ACCESS) 142 | 143 | #define FILE_MAP_WRITE SECTION_MAP_WRITE 144 | #define FILE_MAP_READ SECTION_MAP_READ 145 | #define FILE_MAP_ALL_ACCESS SECTION_ALL_ACCESS 146 | #define FILE_MAP_EXECUTE SECTION_MAP_EXECUTE_EXPLICIT // not included in FILE_MAP_ALL_ACCESS 147 | #define FILE_MAP_COPY 0x00000001 148 | #define FILE_MAP_RESERVE 0x80000000 149 | 150 | #define INVALID_FILE_ATTRIBUTES ((uint32_t)-1) 151 | #define SEC_FILE 0x800000 152 | #define SEC_IMAGE 0x1000000 153 | #define SEC_PROTECTED_IMAGE 0x2000000 154 | #define SEC_RESERVE 0x4000000 155 | #define SEC_COMMIT 0x8000000 156 | #define SEC_NOCACHE 0x10000000 157 | #define SEC_WRITECOMBINE 0x40000000 158 | #define SEC_LARGE_PAGES 0x80000000 159 | 160 | #define MEM_COMMIT 0x1000 161 | #define MEM_RESERVE 0x2000 162 | #define MEM_DECOMMIT 0x4000 163 | #define MEM_RELEASE 0x8000 164 | -------------------------------------------------------------------------------- /fnv1a.py: -------------------------------------------------------------------------------- 1 | def fnv1a(s): 2 | h = 0x811c9dc5 3 | for i in s: 4 | h ^= ord(i) 5 | h *= 0x01000193 6 | h &= 0xFFFFFFFF 7 | return h 8 | --------------------------------------------------------------------------------