MCPcopy Create free account
hub / github.com/Selectively11/CloudRedirect / EnsureExecutableCave

Method EnsureExecutableCave

ui/Services/Patching/Patcher.cs:1051–1106  ·  view source on GitHub ↗
(byte[] payload, PeSection[] sections, int requiredSize)

Source from the content-addressed store, hash-verified

1049 const uint SCN_MEM_EXECUTE = 0x20000000;
1050
1051 int EnsureExecutableCave(byte[] payload, PeSection[] sections, int requiredSize)
1052 {
1053 var peOff = BitConverter.ToInt32(payload, 0x3C);
1054 ushort numSections = BitConverter.ToUInt16(payload, peOff + 6);
1055 ushort optHdrSize = BitConverter.ToUInt16(payload, peOff + 20);
1056 int secHdrStart = peOff + 24 + optHdrSize;
1057 int sectionAlignment = BitConverter.ToInt32(payload, peOff + 0x38);
1058
1059 // Find a read-only section with alignment padding after VSize, extend
1060 // VSize to cover the cave, and add EXECUTE.
1061 for (int s = 0; s < numSections; s++)
1062 {
1063 int hdrOff = secHdrStart + s * 40;
1064 uint chars = BitConverter.ToUInt32(payload, hdrOff + 36);
1065 if ((chars & SCN_MEM_EXECUTE) != 0)
1066 continue;
1067 if ((chars & 0x80000000) != 0) // skip writable sections
1068
1069 continue;
1070
1071 int va = BitConverter.ToInt32(payload, hdrOff + 12);
1072 int vSize = BitConverter.ToInt32(payload, hdrOff + 8);
1073
1074 int alignedEnd = ((va + vSize) + sectionAlignment - 1) & ~(sectionAlignment - 1);
1075 int padGap = alignedEnd - (va + vSize);
1076
1077 if (padGap < requiredSize)
1078 continue;
1079
1080 int caveRva = va + vSize;
1081 int newVSize = vSize + requiredSize;
1082 BitConverter.GetBytes(newVSize).CopyTo(payload, hdrOff + 8);
1083 uint newChars = chars | SCN_MEM_EXECUTE;
1084 BitConverter.GetBytes(newChars).CopyTo(payload, hdrOff + 36);
1085
1086 int rawOff = BitConverter.ToInt32(payload, hdrOff + 20);
1087 int rawSize = BitConverter.ToInt32(payload, hdrOff + 16);
1088 int caveFileOff = rawOff + (caveRva - va);
1089
1090 if (caveFileOff + requiredSize > rawOff + rawSize)
1091 {
1092 if (caveFileOff + requiredSize > payload.Length)
1093 continue;
1094 int newRawSize = ((caveRva - va) + requiredSize + 0x1FF) & ~0x1FF;
1095 BitConverter.GetBytes(newRawSize).CopyTo(payload, hdrOff + 16);
1096 }
1097
1098 string secName = System.Text.Encoding.ASCII.GetString(payload, hdrOff, 8).TrimEnd('\0');
1099 Log($" Cave target: section '{secName}' padding gap ({padGap} bytes)");
1100 Log($" VSize 0x{vSize:X} -> 0x{newVSize:X}, Chars 0x{chars:X8} -> 0x{newChars:X8}");
1101 Log($" Cave RVA 0x{caveRva:X}, file offset 0x{caveFileOff:X}");
1102
1103 return caveFileOff;
1104 }
1105 return -1;
1106 }
1107
1108 PatchEntry[] ResolvePayloadPatchOffsets(byte[] payload)

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected