.Net Core CLR FileFormat Call Method( Include MetaData, Stream, #~)
.Net Core CLR PE 文件启动方法,找到函数入口点,调用整个.Net 程式宿主。
使用方法:可以利用Visual Studio新建一个控制台应用程序,然后生成DLL,替换掉本程序DLL,新建C++ .CPP 文件
然后即可运行看到效果。
整个代码情况如下
包括 IMIAGE_CORE20_HEADER
MetaData, 表格对其方式等待
4 #include "pch.h" 5 #include <iostream> 6 #include <Windows.h> 7 8 #define VAL32(x) x 9 #define VAL16(x) x 10 #define DPTR(type) type* 11 typedef DPTR(IMAGE_DOS_HEADER) PTR_IMAGE_DOS_HEADER; 12 typedef DPTR(IMAGE_NT_HEADERS) PTR_IMAGE_NT_HEADERS; 13 typedef DPTR(IMAGE_NT_HEADERS64) PTR_IMAGE_NT_HEADERS64; 14 typedef ULONG_PTR TADDR; 15 typedef DPTR(IMAGE_DATA_DIRECTORY) PTR_IMAGE_DATA_DIRECTORY; 16 typedef void* PTR_VOID; 17 typedef DPTR(IMAGE_COR20_HEADER) PTR_IMAGE_COR20_HEADER; 18 typedef CONST void far *LPCVOID; 19 20 21 22 23 template <typename Tgt, typename Src> 24 inline Tgt dac_cast(Src src) 25 { 26 #ifdef DACCESS_COMPILE 27 // In DAC builds, first get a TADDR for the source, then create the 28 // appropriate destination instance. 29 TADDR addr = dac_imp::getTaddr(src); 30 return dac_imp::makeDacInst<Tgt>::fromTaddr(addr); 31 #else 32 // In non-DAC builds, dac_cast is the same as a C-style cast because we need to support: 33 // - casting away const 34 // - conversions between pointers and TADDR 35 // Perhaps we should more precisely restrict it's usage, but we get the precise 36 // restrictions in DAC builds, so it wouldn't buy us much. 37 return (Tgt)(src); 38 #endif 39 } 40 TADDR m_base; 41 TADDR m_b; 42 43 44 45 #define ALIGN4BYTE(val) (((val) + 3) & ~0x3) 46 47 struct STORAGEHEADER 48 { 49 public: 50 BYTE fFlags; // STGHDR_xxx flags. 51 BYTE pad; 52 USHORT iStreams; // How many streams are there. 53 public: 54 BYTE GetFlags() 55 { 56 return fFlags; 57 } 58 void SetFlags(BYTE flags) 59 { 60 fFlags = flags; 61 } 62 void AddFlags(BYTE flags) 63 { 64 fFlags |= flags; 65 } 66 67 68 USHORT GetiStreams() 69 { 70 return VAL16(iStreams); 71 } 72 void SetiStreams(USHORT iStreamsCount) 73 { 74 iStreams = VAL16(iStreamsCount); 75 } 76 }; 77 78 struct STORAGESIGNATURE 79 { 80 public: 81 ULONG lSignature; // "Magic" signature. 82 USHORT iMajorVer; // Major file version. 83 USHORT iMinorVer; // Minor file version. 84 ULONG iExtraData; // Offset to next structure of information 85 ULONG iVersionString; // Length of version string 86 public: 87 BYTE pVersion[0]; // Version string 88 ULONG GetSignature() 89 { 90 return VAL32(lSignature); 91 } 92 void SetSignature(ULONG Signature) 93 { 94 lSignature = VAL32(Signature); 95 } 96 97 USHORT GetMajorVer() 98 { 99 return VAL16(iMajorVer); 100 } 101 void SetMajorVer(USHORT MajorVer) 102 { 103 iMajorVer = VAL16(MajorVer); 104 } 105 106 USHORT GetMinorVer() 107 { 108 return VAL16(iMinorVer); 109 } 110 void SetMinorVer(USHORT MinorVer) 111 { 112 iMinorVer = VAL16(MinorVer); 113 } 114 115 ULONG GetExtraDataOffset() 116 { 117 return VAL32(iExtraData); 118 } 119 void SetExtraDataOffset(ULONG ExtraDataOffset) 120 { 121 iExtraData = VAL32(ExtraDataOffset); 122 } 123 124 ULONG GetVersionStringLength() 125 { 126 return VAL32(iVersionString); 127 } 128 void SetVersionStringLength(ULONG VersionStringLength) 129 { 130 iVersionString = VAL32(VersionStringLength); 131 } 132 }; 133 134 struct PSTORAGESIGNATURE 135 { 136 public: 137 ULONG lSignature; // "Magic" signature. 138 USHORT iMajorVer; // Major file version. 139 USHORT iMinorVer; // Minor file version. 140 ULONG iExtraData; // Offset to next structure of information 141 ULONG iVersionString; // Length of version string 142 public: 143 BYTE pVersion[0]; // Version string 144 ULONG GetSignature() 145 { 146 return VAL32(lSignature); 147 } 148 void SetSignature(ULONG Signature) 149 { 150 lSignature = VAL32(Signature); 151 } 152 153 USHORT GetMajorVer() 154 { 155 return VAL16(iMajorVer); 156 } 157 void SetMajorVer(USHORT MajorVer) 158 { 159 iMajorVer = VAL16(MajorVer); 160 } 161 162 USHORT GetMinorVer() 163 { 164 return VAL16(iMinorVer); 165 } 166 void SetMinorVer(USHORT MinorVer) 167 { 168 iMinorVer = VAL16(MinorVer); 169 } 170 171 ULONG GetExtraDataOffset() 172 { 173 return VAL32(iExtraData); 174 } 175 void SetExtraDataOffset(ULONG ExtraDataOffset) 176 { 177 iExtraData = VAL32(ExtraDataOffset); 178 } 179 180 ULONG GetVersionStringLength() 181 { 182 return VAL32(iVersionString); 183 } 184 void SetVersionStringLength(ULONG VersionStringLength) 185 { 186 iVersionString = VAL32(VersionStringLength); 187 } 188 }; 189 190 struct STORAGESTREAM; 191 typedef STORAGESTREAM UNALIGNED * PSTORAGESTREAM; 192 193 194 struct STORAGESTREAM 195 { 196 public: 197 ULONG iOffset; // Offset in file for this stream. 198 ULONG iSize; // Size of the file. 199 char rcName[32]; // Start of name, null terminated. 200 public: 201 // Returns pointer to the next stream. Doesn't validate the structure. 202 inline PSTORAGESTREAM NextStream() 203 { 204 int iLen = (int)(strlen(rcName) + 1); 205 iLen = ALIGN4BYTE(iLen); 206 return ((PSTORAGESTREAM)(((BYTE*)this) + (sizeof(ULONG) * 2) + iLen)); 207 } 208 // Returns pointer to the next stream. 209 // Returns NULL if the structure has invalid format. 210 inline PSTORAGESTREAM NextStream_Verify() 211 { 212 // Check existence of null-terminator in the name 213 if (memchr(rcName, 0, 32) == NULL) 214 { 215 return NULL; 216 } 217 return NextStream(); 218 } 219 220 inline ULONG GetStreamSize() 221 { 222 return (ULONG)(strlen(rcName) + 1 + (sizeof(STORAGESTREAM) - sizeof(rcName))); 223 } 224 225 inline char* GetName() 226 { 227 return rcName; 228 } 229 inline LPCWSTR GetName(__inout_ecount(iMaxSize) LPWSTR szName, int iMaxSize) 230 { 231 //VERIFY(::WszMultiByteToWideChar(CP_ACP, 0, rcName, -1, szName, iMaxSize)); 232 return (szName); 233 } 234 inline void SetName(LPCWSTR szName) 235 { 236 int size; 237 //size = WszWideCharToMultiByte(CP_ACP, 0, szName, -1, rcName, MAXSTREAMNAME, 0, 0); 238 _ASSERTE(size > 0); 239 } 240 241 ULONG GetSize() 242 { 243 return VAL32(iSize); 244 } 245 void SetSize(ULONG Size) 246 { 247 iSize = VAL32(Size); 248 } 249 250 ULONG GetOffset() 251 { 252 return VAL32(iOffset); 253 } 254 void SetOffset(ULONG Offset) 255 { 256 iOffset = VAL32(Offset); 257 } 258 }; 259 260 261 #define UI64_HELPER(x) x ## ui64 262 #define UI64(x) UI64_HELPER(x) 263 264 class CMiniMdSchemaBase 265 { 266 public: 267 ULONG m_ulReserved; // Reserved, must be zero. 268 BYTE m_major; // Version numbers. 269 BYTE m_minor; 270 BYTE m_heaps; // Bits for heap sizes. 271 BYTE m_rid; // log-base-2 of largest rid. 272 273 // Bits for heap sizes. 274 enum { 275 HEAP_STRING_4 = 0x01, 276 HEAP_GUID_4 = 0x02, 277 HEAP_BLOB_4 = 0x04, 278 279 PADDING_BIT = 0x08, // Tables can be created with an extra bit in columns, for growth. 280 281 DELTA_ONLY = 0x20, // If set, only deltas were persisted. 282 EXTRA_DATA = 0x40, // If set, schema persists an extra 4 bytes of data. 283 HAS_DELETE = 0x80, // If set, this metadata can contain _Delete tokens. 284 }; 285 286 unsigned __int64 m_maskvalid; // Bit mask of present table counts. 287 288 unsigned __int64 m_sorted; // Bit mask of sorted tables. 289 FORCEINLINE bool IsSorted(ULONG ixTbl) 290 { 291 return m_sorted & BIT(ixTbl) ? true : false; 292 } 293 void SetSorted(ULONG ixTbl, int bVal) 294 { 295 if (bVal) m_sorted |= BIT(ixTbl); 296 else m_sorted &= ~BIT(ixTbl); 297 } 298 299 #if BIGENDIAN 300 // Verify that the size hasn't changed (Update if necessary) 301 void ConvertEndianness() 302 { 303 _ASSERTE(sizeof(CMiniMdSchemaBase) == 0x18); 304 m_ulReserved = VAL32(m_ulReserved); 305 m_maskvalid = VAL64(m_maskvalid); 306 m_sorted = VAL64(m_sorted); 307 } 308 #else 309 // Nothing to do on little endian machine 310 void ConvertEndianness() { return; } 311 #endif 312 313 private: 314 FORCEINLINE unsigned __int64 BIT(ULONG ixBit) 315 { 316 _ASSERTE(ixBit < (sizeof(__int64)*CHAR_BIT)); 317 return UI64(1) << ixBit; 318 } 319 320 }; 321 322 typedef enum MetadataVersion 323 { 324 MDVersion1 = 0x00000001, 325 MDVersion2 = 0x00000002, 326 327 // @TODO - this value should be updated when we increase the version number 328 MDDefaultVersion = 0x00000002 329 } MetadataVersion; 330 class CMiniMdSchema : public CMiniMdSchemaBase 331 { 332 public: 333 // These are not all persisted to disk. See LoadFrom() for details. 334 ULONG m_cRecs[45]; // Counts of various tables. 335 336 ULONG m_ulExtra; // Extra data, only persisted if non-zero. (m_heaps&EXTRA_DATA flags) 337 338 ULONG LoadFrom(const void*, ULONG); // Load from a compressed version. Return bytes consumed. 339 ULONG SaveTo(void *); // Store a compressed version. Return bytes used in buffer. 340 __checkReturn 341 HRESULT InitNew(MetadataVersion); 342 }; 343 #define GET_UNALIGNED_32(_pObject) (*(UINT32 UNALIGNED *)(_pObject)) 344 #define GET_UNALIGNED_VAL32(_pObject) VAL32(GET_UNALIGNED_32(_pObject)) 345 346 template<typename T> class ClrSafeInt 347 { 348 public: 349 // Default constructor - 0 value by default 350 ClrSafeInt() : 351 m_value(0), 352 m_overflow(false) 353 COMMA_INDEBUG(m_checkedOverflow(false)) 354 { 355 } 356 357 // Value constructor 358 // This is explicit because otherwise it would be harder to 359 // differentiate between checked and unchecked usage of an operator. 360 // I.e. si + x + y vs. si + ( x + y ) 361 // 362 // Set the m_checkedOverflow bit to true since this is being initialized 363 // with a constant value and we know that it is valid. A scenario in 364 // which this is useful is when an overflow causes a fallback value to 365 // be used: 366 // if (val.IsOverflow()) 367 // val = ClrSafeInt<T>(some_value); 368 explicit ClrSafeInt(T v) : 369 m_value(v), 370 m_overflow(false) 371 COMMA_INDEBUG(m_checkedOverflow(true)) 372 { 373 } 374 375 template <typename U> 376 explicit ClrSafeInt(U u) : 377 m_value(0), 378 m_overflow(false) 379 COMMA_INDEBUG(m_checkedOverflow(false)) 380 { 381 if (!FitsIn<T>(u)) 382 { 383 m_overflow = true; 384 } 385 else 386 { 387 m_value = (T)u; 388 } 389 } 390 391 template <typename U> 392 ClrSafeInt(ClrSafeInt<U> u) : 393 m_value(0), 394 m_overflow(false) 395 COMMA_INDEBUG(m_checkedOverflow(false)) 396 { 397 if (u.IsOverflow() || !FitsIn<T>(u.Value())) 398 { 399 m_overflow = true; 400 } 401 else 402 { 403 m_value = (T)u.Value(); 404 } 405 } 406 407 // Note: compiler-generated copy constructor and assignment operator 408 // are correct for our purposes. 409 410 // Note: The MS compiler will sometimes silently perform value-destroying 411 // conversions when calling the operators below. 412 // Eg. "ClrSafeInt<unsigned> s(0); s += int(-1);" will result in s 413 // having the value 0xffffffff without generating a compile-time warning. 414 // Narrowing conversions are generally level 4 warnings so may or may not 415 // be visible. 416 // 417 // In the original SafeInt class, all operators have an 418 // additional overload that takes an arbitrary type U and then safe 419 // conversions are performed (resulting in overflow whenever the value 420 // cannot be preserved). 421 // We could do the same thing, but currently don't because: 422 // - we don't believe there are common cases where this would result in a 423 // security hole. 424 // - the extra complexity isn't worth the benefits 425 // - it would prevent compiler warnings in the cases we do get warnings for. 426 427 428 // true if there has been an overflow leading up to the creation of this 429 // value, false otherwise. 430 // Note that in debug builds we track whether our client called this, 431 // so we should not be calling this method ourselves from within this class. 432 inline bool IsOverflow() const 433 { 434 INDEBUG(m_checkedOverflow = true; ) 435 return m_overflow; 436 } 437 438 // Get the value of this integer. 439 // Must only be called when IsOverflow()==false. If this is called 440 // on overflow we'll assert in Debug and return 0 in release. 441 inline T Value() const 442 { 443 _ASSERTE_SAFEMATH(m_checkedOverflow); // Ensure our caller first checked the overflow bit 444 _ASSERTE_SAFEMATH(!m_overflow); 445 return m_value; 446 } 447 448 // force the value into the overflow state. 449 inline void SetOverflow() 450 { 451 INDEBUG(this->m_checkedOverflow = false; ) 452 this->m_overflow = true; 453 // incase someone manages to call Value in release mode - should be optimized out 454 this->m_value = 0; 455 } 456 457 458 // 459 // OPERATORS 460 // 461 462 // Addition and multiplication. Only permitted when both sides are explicitly 463 // wrapped inside of a ClrSafeInt and when the types match exactly. 464 // If we permitted a RHS of type 'T', then there would be differences 465 // in correctness between mathematically equivalent expressions such as 466 // "si + x + y" and "si + ( x + y )". Unfortunately, not permitting this 467 // makes expressions involving constants tedius and ugly since the constants 468 // must be wrapped in ClrSafeInt instances. If we become confident that 469 // our tools (PreFast) will catch all integer overflows, then we can probably 470 // safely add this. 471 inline ClrSafeInt<T> operator +(ClrSafeInt<T> rhs) const 472 { 473 ClrSafeInt<T> result; // value is initialized to 0 474 if (this->m_overflow || 475 rhs.m_overflow || 476 !addition(this->m_value, rhs.m_value, result.m_value)) 477 { 478 result.m_overflow = true; 479 } 480 481 return result; 482 } 483 484 inline ClrSafeInt<T> operator -(ClrSafeInt<T> rhs) const 485 { 486 ClrSafeInt<T> result; // value is initialized to 0 487 if (this->m_overflow || 488 rhs.m_overflow || 489 !subtraction(this->m_value, rhs.m_value, result.m_value)) 490 { 491 result.m_overflow = true; 492 } 493 494 return result; 495 } 496 497 inline ClrSafeInt<T> operator *(ClrSafeInt<T> rhs) const 498 { 499 ClrSafeInt<T> result; // value is initialized to 0 500 if (this->m_overflow || 501 rhs.m_overflow || 502 !multiply(this->m_value, rhs.m_value, result.m_value)) 503 { 504 result.m_overflow = true; 505 } 506 507 return result; 508 } 509 510 // Accumulation operators 511 // Here it's ok to have versions that take a value of type 'T', however we still 512 // don't allow any mixed-type operations. 513 inline ClrSafeInt<T>& operator +=(ClrSafeInt<T> rhs) 514 { 515 INDEBUG(this->m_checkedOverflow = false; ) 516 if (this->m_overflow || 517 rhs.m_overflow || 518 !ClrSafeInt<T>::addition(this->m_value, rhs.m_value, this->m_value)) 519 { 520 this->SetOverflow(); 521 } 522 return *this; 523 } 524 525 inline ClrSafeInt<T>& operator +=(T rhs) 526 { 527 INDEBUG(this->m_checkedOverflow = false; ) 528 if (this->m_overflow || 529 !ClrSafeInt<T>::addition(this->m_value, rhs, this->m_value)) 530 { 531 this->SetOverflow(); 532 } 533 return *this; 534 } 535 536 inline ClrSafeInt<T>& operator *=(ClrSafeInt<T> rhs) 537 { 538 INDEBUG(this->m_checkedOverflow = false; ) 539 if (this->m_overflow || 540 rhs.m_overflow || 541 !ClrSafeInt<T>::multiply(this->m_value, rhs.m_value, this->m_value)) 542 { 543 this->SetOverflow(); 544 } 545 return *this; 546 } 547 548 inline ClrSafeInt<T>& operator *=(T rhs) 549 { 550 INDEBUG(this->m_checkedOverflow = false; ) 551 if (this->m_overflow || 552 !ClrSafeInt<T>::multiply(this->m_value, rhs, this->m_value)) 553 { 554 this->SetOverflow(); 555 } 556 557 return *this; 558 } 559 560 // 561 // STATIC HELPER METHODS 562 //these compile down to something as efficient as macros and allow run-time testing 563 //of type by the developer 564 // 565 566 template <typename U> static bool IsSigned(U) 567 { 568 return std::is_signed<U>::value; 569 } 570 571 static bool IsSigned() 572 { 573 return std::is_signed<T>::value; 574 } 575 576 static bool IsMixedSign(T lhs, T rhs) 577 { 578 return ((lhs ^ rhs) < 0); 579 } 580 581 static unsigned char BitCount() { return (sizeof(T) * 8); } 582 583 static bool Is64Bit() { return sizeof(T) == 8; } 584 static bool Is32Bit() { return sizeof(T) == 4; } 585 static bool Is16Bit() { return sizeof(T) == 2; } 586 static bool Is8Bit() { return sizeof(T) == 1; } 587 588 //both of the following should optimize away 589 static T MaxInt() 590 { 591 if (IsSigned()) 592 { 593 return (T)~((T)1 << (BitCount() - 1)); 594 } 595 //else 596 return (T)(~(T)0); 597 } 598 599 static T MinInt() 600 { 601 if (IsSigned()) 602 { 603 return (T)((T)1 << (BitCount() - 1)); 604 } 605 else 606 { 607 return ((T)0); 608 } 609 } 610 611 // Align a value up to the nearest boundary, which must be a power of 2 612 inline void AlignUp(T alignment) 613 { 614 _ASSERTE_SAFEMATH(IsPowerOf2(alignment)); 615 *this += (alignment - 1); 616 if (!this->m_overflow) 617 { 618 m_value &= ~(alignment - 1); 619 } 620 } 621 622 // 623 // Arithmetic implementation functions 624 // 625 626 //note - this looks complex, but most of the conditionals 627 //are constant and optimize away 628 //for example, a signed 64-bit check collapses to: 629 /* 630 if(lhs == 0 || rhs == 0) 631 return 0; 632 633 if(MaxInt()/+lhs < +rhs) 634 { 635 //overflow 636 throw SafeIntException(ERROR_ARITHMETIC_OVERFLOW); 637 } 638 //ok 639 return lhs * rhs; 640 641 Which ought to inline nicely 642 */ 643 // Returns true if safe, false for overflow. 644 static bool multiply(T lhs, T rhs, T &result) 645 { 646 if (Is64Bit()) 647 { 648 //fast track this one - and avoid DIV_0 below 649 if (lhs == 0 || rhs == 0) 650 { 651 result = 0; 652 return true; 653 } 654 655 //we're 64 bit - slow, but the only way to do it 656 if (IsSigned()) 657 { 658 if (!IsMixedSign(lhs, rhs)) 659 { 660 //both positive or both negative 661 //result will be positive, check for lhs * rhs > MaxInt 662 if (lhs > 0) 663 { 664 //both positive 665 if (MaxInt() / lhs < rhs) 666 { 667 //overflow 668 return false; 669 } 670 } 671 else 672 { 673 //both negative 674 675 //comparison gets tricky unless we force it to positive 676 //EXCEPT that -MinInt is undefined - can't be done 677 //And MinInt always has a greater magnitude than MaxInt 678 if (lhs == MinInt() || rhs == MinInt()) 679 { 680 //overflow 681 return false; 682 } 683 684 #ifdef _MSC_VER 685 #pragma warning( disable : 4146 ) // unary minus applied to unsigned is still unsigned 686 #endif 687 if (MaxInt() / (-lhs) < (-rhs)) 688 { 689 //overflow 690 return false; 691 } 692 #ifdef _MSC_VER 693 #pragma warning( default : 4146 ) 694 #endif 695 } 696 } 697 else 698 { 699 //mixed sign - this case is difficult 700 //test case is lhs * rhs < MinInt => overflow 701 //if lhs < 0 (implies rhs > 0), 702 //lhs < MinInt/rhs is the correct test 703 //else if lhs > 0 704 //rhs < MinInt/lhs is the correct test 705 //avoid dividing MinInt by a negative number, 706 //because MinInt/-1 is a corner case 707 708 if (lhs < 0) 709 { 710 if (lhs < MinInt() / rhs) 711 { 712 //overflow 713 return false; 714 } 715 } 716 else 717 { 718 if (rhs < MinInt() / lhs) 719 { 720 //overflow 721 return false; 722 } 723 } 724 } 725 726 //ok 727 result = lhs * rhs; 728 return true; 729 } 730 else 731 { 732 //unsigned, easy case 733 if (MaxInt() / lhs < rhs) 734 { 735 //overflow 736 return false; 737 } 738 //ok 739 result = lhs * rhs; 740 return true; 741 } 742 } 743 else if (Is32Bit()) 744 { 745 //we're 32-bit 746 if (IsSigned()) 747 { 748 INT64 tmp = (INT64)lhs * (INT64)rhs; 749 750 //upper 33 bits must be the same 751 //most common case is likely that both are positive - test first 752 if ((tmp & 0xffffffff80000000LL) == 0 || 753 (tmp & 0xffffffff80000000LL) == 0xffffffff80000000LL) 754 { 755 //this is OK 756 result = (T)tmp; 757 return true; 758 } 759 760 //overflow 761 return false; 762 763 } 764 else 765 { 766 UINT64 tmp = (UINT64)lhs * (UINT64)rhs; 767 if (tmp & 0xffffffff00000000ULL) //overflow 768 { 769 //overflow 770 return false; 771 } 772 result = (T)tmp; 773 return true; 774 } 775 } 776 else if (Is16Bit()) 777 { 778 //16-bit 779 if (IsSigned()) 780 { 781 INT32 tmp = (INT32)lhs * (INT32)rhs; 782 //upper 17 bits must be the same 783 //most common case is likely that both are positive - test first 784 if ((tmp & 0xffff8000) == 0 || (tmp & 0xffff8000) == 0xffff8000) 785 { 786 //this is OK 787 result = (T)tmp; 788 return true; 789 } 790 791 //overflow 792 return false; 793 } 794 else 795 { 796 UINT32 tmp = (UINT32)lhs * (UINT32)rhs; 797 if (tmp & 0xffff0000) //overflow 798 { 799 return false; 800 } 801 result = (T)tmp; 802 return true; 803 } 804 } 805 else //8-bit 806 { 807 _ASSERTE_SAFEMATH(Is8Bit()); 808 809 if (IsSigned()) 810 { 811 INT16 tmp = (INT16)lhs * (INT16)rhs; 812 //upper 9 bits must be the same 813 //most common case is likely that both are positive - test first 814 if ((tmp & 0xff80) == 0 || (tmp & 0xff80) == 0xff80) 815 { 816 //this is OK 817 result = (T)tmp; 818 return true; 819 } 820 821 //overflow 822 return false; 823 } 824 else 825 { 826 UINT16 tmp = ((UINT16)lhs) * ((UINT16)rhs); 827 828 if (tmp & 0xff00) //overflow 829 { 830 return false; 831 } 832 result = (T)tmp; 833 return true; 834 } 835 } 836 } 837 838 // Returns true if safe, false on overflow 839 static inline bool addition(T lhs, T rhs, T &result) 840 { 841 if (IsSigned()) 842 { 843 //test for +/- combo 844 if (!IsMixedSign(lhs, rhs)) 845 { 846 //either two negatives, or 2 positives 847 #ifdef __GNUC__ 848 // Workaround for GCC warning: "comparison is always 849 // false due to limited range of data type." 850 if (!(rhs == 0 || rhs > 0)) 851 #else 852 if (rhs < 0) 853 #endif // __GNUC__ else 854 { 855 //two negatives 856 if (lhs < (T)(MinInt() - rhs)) //remember rhs < 0 857 { 858 return false; 859 } 860 //ok 861 } 862 else 863 { 864 //two positives 865 if ((T)(MaxInt() - lhs) < rhs) 866 { 867 return false; 868 } 869 //OK 870 } 871 } 872 //else overflow not possible 873 result = lhs + rhs; 874 return true; 875 } 876 else //unsigned 877 { 878 if ((T)(MaxInt() - lhs) < rhs) 879 { 880 return false; 881 882 } 883 result = lhs + rhs; 884 return true; 885 } 886 } 887 888 // Returns true if safe, false on overflow 889 static inline bool subtraction(T lhs, T rhs, T& result) 890 { 891 T tmp = lhs - rhs; 892 893 if (IsSigned()) 894 { 895 if (IsMixedSign(lhs, rhs)) //test for +/- combo 896 { 897 //mixed positive and negative 898 //two cases - +X - -Y => X + Y - check for overflow against MaxInt() 899 // -X - +Y - check for overflow against MinInt() 900 901 if (lhs >= 0) //first case 902 { 903 //test is X - -Y > MaxInt() 904 //equivalent to X > MaxInt() - |Y| 905 //Y == MinInt() creates special case 906 //Even 0 - MinInt() can't be done 907 //note that the special case collapses into the general case, due to the fact 908 //MaxInt() - MinInt() == -1, and lhs is non-negative 909 //OR tmp should be GTE lhs 910 911 // old test - leave in for clarity 912 //if(lhs > (T)(MaxInt() + rhs)) //remember that rhs is negative 913 if (tmp < lhs) 914 { 915 return false; 916 } 917 //fall through to return value 918 } 919 else 920 { 921 //second case 922 //test is -X - Y < MinInt() 923 //or -X < MinInt() + Y 924 //we do not have the same issues because abs(MinInt()) > MaxInt() 925 //tmp should be LTE lhs 926 927 //if(lhs < (T)(MinInt() + rhs)) // old test - leave in for clarity 928 if (tmp > lhs) 929 { 930 return false; 931 } 932 //fall through to return value 933 } 934 } 935 // else 936 //both negative, or both positive 937 //no possible overflow 938 result = tmp; 939 return true; 940 } 941 else 942 { 943 //easy unsigned case 944 if (lhs < rhs) 945 { 946 return false; 947 } 948 result = tmp; 949 return true; 950 } 951 } 952 953 private: 954 // Private helper functions 955 // Note that's it occasionally handy to call the arithmetic implementation 956 // functions above so we leave them public, even though we almost always use 957 // the operators instead. 958 959 // True if the specified value is a power of two. 960 static inline bool IsPowerOf2(T x) 961 { 962 // find the smallest power of 2 >= x 963 T testPow = 1; 964 while (testPow < x) 965 { 966 testPow = testPow << 1; // advance to next power of 2 967 if (testPow <= 0) 968 { 969 return false; // overflow 970 } 971 } 972 973 return(testPow == x); 974 } 975 976 // 977 // Instance data 978 // 979 980 // The integer value this instance represents, or 0 if overflow. 981 T m_value; 982 983 // True if overflow has been reached. Once this is set, it cannot be cleared. 984 bool m_overflow; 985 986 // In debug builds we verify that our caller checked the overflow bit before 987 // accessing the value. This flag is cleared on initialization, and whenever 988 // m_value or m_overflow changes, and set only when IsOverflow 989 // is called. 990 INDEBUG(mutable bool m_checkedOverflow; ) 991 }; 992 993 ULONG 994 CMiniMdSchema::LoadFrom( 995 const void *pvData, // Data to load from. 996 ULONG cbData) // Amount of data available. 997 { 998 ULONG ulData; // Bytes consumed. 999 1000 ulData = sizeof(CMiniMdSchemaBase); 1001 1002 // Be sure we can get the base part. 1003 if (cbData < ulData) 1004 return (ULONG)(-1); 1005 1006 // Transfer the fixed fields. The (void*) casts prevents the compiler 1007 // from making bad assumptions about the alignment. 1008 memcpy((void *)this, (void *)pvData, sizeof(CMiniMdSchemaBase)); 1009 static_cast<CMiniMdSchemaBase*>(this)->ConvertEndianness(); 1010 1011 unsigned __int64 maskvalid = m_maskvalid; 1012 1013 // Transfer the variable fields. 1014 memset(m_cRecs, 0, sizeof(m_cRecs)); 1015 int iDst; 1016 for (iDst = 0; iDst < 45; ++iDst, maskvalid >>= 1) 1017 { 1018 if ((maskvalid & 1) != 0) 1019 { 1020 // Check integer overflow for: ulData + sizeof(UINT32) 1021 ULONG ulDataTemp; 1022 if (!ClrSafeInt<ULONG>::addition(ulData, sizeof(UINT32), ulDataTemp)) 1023 { 1024 return (ULONG)(-1); 1025 } 1026 // Verify that the data is there before touching it. 1027 if (cbData < (ulData + sizeof(UINT32))) 1028 return (ULONG)(-1); 1029 1030 m_cRecs[iDst] = GET_UNALIGNED_VAL32((const BYTE *)pvData + ulData); 1031 // It's safe to sum, because we checked integer overflow above 1032 ulData += sizeof(UINT32); 1033 } 1034 } 1035 // Also accumulate the sizes of any counters that we don't understand. 1036 1037 1038 // Retrieve the extra 4 bytes data. 1039 // Did we go past end of buffer? 1040 if (cbData < ulData) 1041 return (ULONG)(-1); 1042 1043 return ulData; 1044 } // CMiniMdSchema::LoadFrom 1045 1046 int main() 1047 { 1048 HMODULE HE=LoadLibraryExW(L"C:\\Users\\Administrator\\Desktop\\Consletest\\ConsoleApp5.dll", NULL, 8); 1049 //0x00007ff82c940000 1050 //0x00007ff82e1c0000 1051 1052 m_base=TADDR((void *)HE); 1053 1054 IMAGE_DOS_HEADER *SR =dac_cast<PTR_IMAGE_DOS_HEADER>(PTR_IMAGE_DOS_HEADER(HE)); 1055 1056 IMAGE_NT_HEADERS *HR =dac_cast<PTR_IMAGE_NT_HEADERS64>(PTR_IMAGE_NT_HEADERS(m_base + VAL32(SR->e_lfanew))); 1057 1058 IMAGE_DATA_DIRECTORY *pDir=dac_cast<PTR_IMAGE_DATA_DIRECTORY>(dac_cast<TADDR>(dac_cast<PTR_IMAGE_NT_HEADERS64>(PTR_IMAGE_NT_HEADERS(m_base + VAL32(PTR_IMAGE_DOS_HEADER(HE)->e_lfanew)))) + 1059 offsetof(IMAGE_NT_HEADERS64, OptionalHeader.DataDirectory) + 14 * sizeof(IMAGE_DATA_DIRECTORY)); 1060 1061 1062 IMAGE_COR20_HEADER *OR = PTR_IMAGE_COR20_HEADER(m_base + VAL32(pDir->VirtualAddress)); 1063 1064 IMAGE_DATA_DIRECTORY *DR =&(OR->MetaData); 1065 1066 const void* pMeta = NULL; 1067 1068 pMeta=dac_cast<PTR_VOID>(VAL32(m_base+DR->VirtualAddress)); 1069 1070 ULONG cbStreamBuffer; 1071 1072 const BYTE *pbMd; 1073 1074 pbMd = (const BYTE *)pMeta; 1075 1076 1077 pbMd += sizeof(STORAGESIGNATURE); 1078 1079 ULONG cbVersionString = ((STORAGESIGNATURE *)pMeta)->GetVersionStringLength(); 1080 1081 pbMd += cbVersionString; 1082 1083 pbMd += sizeof(STORAGEHEADER); 1084 1085 PSTORAGESTREAM pStream; 1086 1087 pStream = (PSTORAGESTREAM)pbMd; 1088 1089 int i; 1090 CMiniMdSchema m_Schema; 1091 ULONG cbData; 1092 ULONG cb; 1093 for (i = 0; i < 5; i++) 1094 { 1095 void *pvCurrentData = (void *)((BYTE *)pMeta + pStream->GetOffset()); 1096 1097 ULONG cbCurrentData = pStream->GetSize(); 1098 1099 PSTORAGESTREAM pNext = pStream->NextStream_Verify(); 1100 1101 if (pStream->GetName() == "#~") 1102 { 1103 cbData = sizeof(CMiniMdSchemaBase); 1104 cb=m_Schema.LoadFrom(pvCurrentData, cbCurrentData); 1105 } 1106 pStream = pNext; 1107 } 1108 1109 1110 std::cout << "Hello World!\n"; 1111 }