macOS .Net Applications Injection

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ

์ด๊ฒƒ์€ ๊ฒŒ์‹œ๋ฌผ https://blog.xpnsec.com/macos-injection-via-third-party-frameworks/์˜ ์š”์•ฝ์ž…๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ํ™•์ธํ•˜์„ธ์š”!

.NET Core Debugging

๋””๋ฒ„๊น… ์„ธ์…˜ ์„ค์ •

.NET์—์„œ ๋””๋ฒ„๊ฑฐ์™€ ๋””๋ฒ„๊ทธ ๋Œ€์ƒ ๊ฐ„์˜ ํ†ต์‹  ์ฒ˜๋ฆฌ๋Š” dbgtransportsession.cpp์—์„œ ๊ด€๋ฆฌ๋ฉ๋‹ˆ๋‹ค. ์ด ๊ตฌ์„ฑ ์š”์†Œ๋Š” dbgtransportsession.cpp#L127์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด ๊ฐ .NET ํ”„๋กœ์„ธ์Šค์— ๋Œ€ํ•ด ๋‘ ๊ฐœ์˜ ๋ช…๋ช…๋œ ํŒŒ์ดํ”„๋ฅผ ์„ค์ •ํ•˜๋ฉฐ, ์ด๋Š” twowaypipe.cpp#L27๋ฅผ ํ†ตํ•ด ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํŒŒ์ดํ”„๋Š” -in ๋ฐ **-out**์œผ๋กœ ์ ‘๋ฏธ์‚ฌ๊ฐ€ ๋ถ™์Šต๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž์˜ **$TMPDIR**๋ฅผ ๋ฐฉ๋ฌธํ•˜๋ฉด .Net ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋””๋ฒ„๊น…ํ•˜๊ธฐ ์œ„ํ•œ ๋””๋ฒ„๊น… FIFO๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

DbgTransportSession::TransportWorker๋Š” ๋””๋ฒ„๊ฑฐ๋กœ๋ถ€ํ„ฐ์˜ ํ†ต์‹  ๊ด€๋ฆฌ๋ฅผ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค. ์ƒˆ๋กœ์šด ๋””๋ฒ„๊น… ์„ธ์…˜์„ ์‹œ์ž‘ํ•˜๋ ค๋ฉด, ๋””๋ฒ„๊ฑฐ๋Š” MessageHeader ๊ตฌ์กฐ์ฒด๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ฉ”์‹œ์ง€๋ฅผ out ํŒŒ์ดํ”„๋ฅผ ํ†ตํ•ด ์ „์†กํ•ด์•ผ ํ•˜๋ฉฐ, ์ด๋Š” .NET ์†Œ์Šค ์ฝ”๋“œ์— ์ž์„ธํžˆ ์„ค๋ช…๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค:

struct MessageHeader {
MessageType   m_eType;        // Message type
DWORD         m_cbDataBlock;  // Size of following data block (can be zero)
DWORD         m_dwId;         // Message ID from sender
DWORD         m_dwReplyId;    // Reply-to Message ID
DWORD         m_dwLastSeenId; // Last seen Message ID by sender
DWORD         m_dwReserved;   // Reserved for future (initialize to zero)
union {
struct {
DWORD         m_dwMajorVersion;   // Requested/accepted protocol version
DWORD         m_dwMinorVersion;
} VersionInfo;
...
} TypeSpecificData;
BYTE          m_sMustBeZero[8];
}

์ƒˆ ์„ธ์…˜์„ ์š”์ฒญํ•˜๊ธฐ ์œ„ํ•ด ์ด ๊ตฌ์กฐ์ฒด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฑ„์›Œ์ง€๋ฉฐ, ๋ฉ”์‹œ์ง€ ์œ ํ˜•์„ MT_SessionRequest๋กœ ์„ค์ •ํ•˜๊ณ  ํ”„๋กœํ† ์ฝœ ๋ฒ„์ „์„ ํ˜„์žฌ ๋ฒ„์ „์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค:

static const DWORD kCurrentMajorVersion = 2;
static const DWORD kCurrentMinorVersion = 0;

// Configure the message type and version
sSendHeader.m_eType = MT_SessionRequest;
sSendHeader.TypeSpecificData.VersionInfo.m_dwMajorVersion = kCurrentMajorVersion;
sSendHeader.TypeSpecificData.VersionInfo.m_dwMinorVersion = kCurrentMinorVersion;
sSendHeader.m_cbDataBlock = sizeof(SessionRequestData);

์ด ํ—ค๋”๋Š” write ์‹œ์Šคํ…œ ํ˜ธ์ถœ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋Œ€์ƒ์— ์ „์†ก๋˜๋ฉฐ, ๊ทธ ๋’ค์— ์„ธ์…˜์„ ์œ„ํ•œ GUID๋ฅผ ํฌํ•จํ•˜๋Š” sessionRequestData ๊ตฌ์กฐ์ฒด๊ฐ€ ์˜ต๋‹ˆ๋‹ค:

write(wr, &sSendHeader, sizeof(MessageHeader));
memset(&sDataBlock.m_sSessionID, 9, sizeof(SessionRequestData));
write(wr, &sDataBlock, sizeof(SessionRequestData));

out ํŒŒ์ดํ”„์—์„œ์˜ ์ฝ๊ธฐ ์ž‘์—…์€ ๋””๋ฒ„๊น… ์„ธ์…˜ ์„ค์ •์˜ ์„ฑ๊ณต ๋˜๋Š” ์‹คํŒจ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค:

read(rd, &sReceiveHeader, sizeof(MessageHeader));

๋ฉ”๋ชจ๋ฆฌ ์ฝ๊ธฐ

๋””๋ฒ„๊น… ์„ธ์…˜์ด ์„ค์ •๋˜๋ฉด MT_ReadMemory ๋ฉ”์‹œ์ง€ ์œ ํ˜•์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•จ์ˆ˜ readMemory๋Š” ์ฝ๊ธฐ ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ์‘๋‹ต์„ ๊ฒ€์ƒ‰ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋‹จ๊ณ„๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ์ž์„ธํ•œ ๋‚ด์šฉ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค:

bool readMemory(void *addr, int len, unsigned char **output) {
// Allocation and initialization
...
// Write header and read response
...
// Read the memory from the debuggee
...
return true;
}

์™„์ „ํ•œ ๊ฐœ๋… ์ฆ๋ช…(POC)์€ ์—ฌ๊ธฐ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฉ”๋ชจ๋ฆฌ ์“ฐ๊ธฐ

์œ ์‚ฌํ•˜๊ฒŒ, writeMemory ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์“ธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์€ ๋ฉ”์‹œ์ง€ ์œ ํ˜•์„ MT_WriteMemory๋กœ ์„ค์ •ํ•˜๊ณ , ๋ฐ์ดํ„ฐ์˜ ์ฃผ์†Œ์™€ ๊ธธ์ด๋ฅผ ์ง€์ •ํ•œ ๋‹ค์Œ, ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๋Š” ๊ฒƒ์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค:

bool writeMemory(void *addr, int len, unsigned char *input) {
// Increment IDs, set message type, and specify memory location
...
// Write header and data, then read the response
...
// Confirm memory write was successful
...
return true;
}

์—ฐ๊ด€๋œ POC๋Š” ์—ฌ๊ธฐ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

.NET Core ์ฝ”๋“œ ์‹คํ–‰

์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ ค๋ฉด rwx ๊ถŒํ•œ์ด ์žˆ๋Š” ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์„ ์‹๋ณ„ํ•ด์•ผ ํ•˜๋ฉฐ, ์ด๋Š” vmmap -pages:๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

vmmap -pages [pid]
vmmap -pages 35829 | grep "rwx/rwx"

ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๋ฅผ ๋ฎ์–ด์“ธ ์œ„์น˜๋ฅผ ์ฐพ๋Š” ๊ฒƒ์€ ํ•„์š”ํ•˜๋ฉฐ, .NET Core์—์„œ๋Š” **Dynamic Function Table (DFT)**๋ฅผ ํƒ€๊ฒŸํŒ…ํ•˜์—ฌ ์ด๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํ…Œ์ด๋ธ”์€ jithelpers.h์—์„œ ์ž์„ธํžˆ ์„ค๋ช…๋˜์–ด ์žˆ์œผ๋ฉฐ, ๋Ÿฐํƒ€์ž„์—์„œ JIT ์ปดํŒŒ์ผ ํ—ฌํผ ํ•จ์ˆ˜์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

x64 ์‹œ์Šคํ…œ์˜ ๊ฒฝ์šฐ, ์„œ๋ช… ๊ฒ€์ƒ‰์„ ์‚ฌ์šฉํ•˜์—ฌ libcorclr.dll์—์„œ ์‹ฌ๋ณผ _hlpDynamicFuncTable์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

MT_GetDCB ๋””๋ฒ„๊ฑฐ ํ•จ์ˆ˜๋Š” ํ—ฌํผ ํ•จ์ˆ˜์˜ ์ฃผ์†Œ์ธ m_helperRemoteStartAddr๋ฅผ ํฌํ•จํ•˜์—ฌ ์œ ์šฉํ•œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ํ”„๋กœ์„ธ์Šค ๋ฉ”๋ชจ๋ฆฌ์—์„œ libcorclr.dll์˜ ์œ„์น˜๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์ด ์ฃผ์†Œ๋Š” DFT๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ  ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๋ฅผ ์…ธ์ฝ”๋“œ์˜ ์ฃผ์†Œ๋กœ ๋ฎ์–ด์“ฐ๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

PowerShell์— ๋Œ€ํ•œ ์ฃผ์ž…์„ ์œ„ํ•œ ์ „์ฒด POC ์ฝ”๋“œ๋Š” ์—ฌ๊ธฐ์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

References

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ