macOS Thread Injection via Task port

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 ์ง€์›ํ•˜๊ธฐ

Code

1. Thread Hijacking

์ฒ˜์Œ์—, task_threads() ํ•จ์ˆ˜๊ฐ€ ์›๊ฒฉ ์ž‘์—…์—์„œ ์Šค๋ ˆ๋“œ ๋ชฉ๋ก์„ ์–ป๊ธฐ ์œ„ํ•ด ์ž‘์—… ํฌํŠธ์—์„œ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ์Šค๋ ˆ๋“œ๊ฐ€ ํ•˜์ด์žฌํ‚น์„ ์œ„ํ•ด ์„ ํƒ๋ฉ๋‹ˆ๋‹ค. ์ด ์ ‘๊ทผ ๋ฐฉ์‹์€ thread_create_running()์„ ์ฐจ๋‹จํ•˜๋Š” ์™„ํ™” ์กฐ์น˜๋กœ ์ธํ•ด ์ƒˆ๋กœ์šด ์›๊ฒฉ ์Šค๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ด ๊ธˆ์ง€๋˜๋ฏ€๋กœ ๊ธฐ์กด์˜ ์ฝ”๋“œ ์ฃผ์ž… ๋ฐฉ๋ฒ•๊ณผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

์Šค๋ ˆ๋“œ๋ฅผ ์ œ์–ดํ•˜๊ธฐ ์œ„ํ•ด thread_suspend()๊ฐ€ ํ˜ธ์ถœ๋˜์–ด ์‹คํ–‰์ด ์ค‘๋‹จ๋ฉ๋‹ˆ๋‹ค.

์›๊ฒฉ ์Šค๋ ˆ๋“œ์—์„œ ํ—ˆ์šฉ๋˜๋Š” ์œ ์ผํ•œ ์ž‘์—…์€ ์ค‘์ง€ ๋ฐ ์‹œ์ž‘๊ณผ ๋ ˆ์ง€์Šคํ„ฐ ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๊ณ /์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์›๊ฒฉ ํ•จ์ˆ˜ ํ˜ธ์ถœ์€ ๋ ˆ์ง€์Šคํ„ฐ x0์—์„œ x7์„ ์ธ์ˆ˜๋กœ ์„ค์ •ํ•˜๊ณ , pc๋ฅผ ์›ํ•˜๋Š” ํ•จ์ˆ˜๋กœ ์„ค์ •ํ•œ ํ›„ ์Šค๋ ˆ๋“œ๋ฅผ ์žฌ๊ฐœํ•˜์—ฌ ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค. ๋ฐ˜ํ™˜ ํ›„ ์Šค๋ ˆ๋“œ๊ฐ€ ์ถฉ๋Œํ•˜์ง€ ์•Š๋„๋ก ํ•˜๋ ค๋ฉด ๋ฐ˜ํ™˜์„ ๊ฐ์ง€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ•œ ๊ฐ€์ง€ ์ „๋žต์€ thread_set_exception_ports()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›๊ฒฉ ์Šค๋ ˆ๋“œ์— ๋Œ€ํ•œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๊ธฐ๋ฅผ ๋“ฑ๋กํ•˜๊ณ , ํ•จ์ˆ˜ ํ˜ธ์ถœ ์ „์— lr ๋ ˆ์ง€์Šคํ„ฐ๋ฅผ ์ž˜๋ชป๋œ ์ฃผ์†Œ๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ํ•จ์ˆ˜ ์‹คํ–‰ ํ›„ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œ์ผœ ์˜ˆ์™ธ ํฌํŠธ์— ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•˜๊ณ , ์Šค๋ ˆ๋“œ์˜ ์ƒํƒœ๋ฅผ ๊ฒ€์‚ฌํ•˜์—ฌ ๋ฐ˜ํ™˜ ๊ฐ’์„ ๋ณต๊ตฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ๋˜๋Š” Ian Beer์˜ triple_fetch ์ต์Šคํ”Œ๋กœ์ž‡์—์„œ ์ฑ„ํƒํ•œ ๋Œ€๋กœ, lr์„ ๋ฌดํ•œ ๋ฃจํ”„์— ์„ค์ •ํ•˜์—ฌ ์Šค๋ ˆ๋“œ์˜ ๋ ˆ์ง€์Šคํ„ฐ๋ฅผ ์ง€์†์ ์œผ๋กœ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๋‹ค๊ฐ€ pc๊ฐ€ ํ•ด๋‹น ๋ช…๋ น์–ด๋ฅผ ๊ฐ€๋ฆฌํ‚ฌ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.

2. Mach ports for communication

๋‹ค์Œ ๋‹จ๊ณ„๋Š” ์›๊ฒฉ ์Šค๋ ˆ๋“œ์™€์˜ ํ†ต์‹ ์„ ์šฉ์ดํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด Mach ํฌํŠธ๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํฌํŠธ๋Š” ์ž‘์—… ๊ฐ„์— ์ž„์˜์˜ ์†ก์‹ /์ˆ˜์‹  ๊ถŒํ•œ์„ ์ „์†กํ•˜๋Š” ๋ฐ ํ•„์ˆ˜์ ์ž…๋‹ˆ๋‹ค.

์–‘๋ฐฉํ–ฅ ํ†ต์‹ ์„ ์œ„ํ•ด ๋‘ ๊ฐœ์˜ Mach ์ˆ˜์‹  ๊ถŒํ•œ์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค: ํ•˜๋‚˜๋Š” ๋กœ์ปฌ ์ž‘์—…์—, ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ์›๊ฒฉ ์ž‘์—…์— ์žˆ์Šต๋‹ˆ๋‹ค. ์ดํ›„ ๊ฐ ํฌํŠธ์— ๋Œ€ํ•œ ์†ก์‹  ๊ถŒํ•œ์ด ์ƒ๋Œ€ ์ž‘์—…์œผ๋กœ ์ „์†ก๋˜์–ด ๋ฉ”์‹œ์ง€ ๊ตํ™˜์ด ๊ฐ€๋Šฅํ•ด์ง‘๋‹ˆ๋‹ค.

๋กœ์ปฌ ํฌํŠธ์— ์ง‘์ค‘ํ•˜๋ฉด, ์ˆ˜์‹  ๊ถŒํ•œ์€ ๋กœ์ปฌ ์ž‘์—…์— ์˜ํ•ด ๋ณด์œ ๋ฉ๋‹ˆ๋‹ค. ํฌํŠธ๋Š” mach_port_allocate()๋กœ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ์ด ํฌํŠธ์— ์†ก์‹  ๊ถŒํ•œ์„ ์›๊ฒฉ ์ž‘์—…์œผ๋กœ ์ „์†กํ•˜๋Š” ๊ฒƒ์ด ๋„์ „ ๊ณผ์ œ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

์ „๋žต์€ thread_set_special_port()๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์›๊ฒฉ ์Šค๋ ˆ๋“œ์˜ THREAD_KERNEL_PORT์— ๋กœ์ปฌ ํฌํŠธ์— ๋Œ€ํ•œ ์†ก์‹  ๊ถŒํ•œ์„ ๋ฐฐ์น˜ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์›๊ฒฉ ์Šค๋ ˆ๋“œ์— mach_thread_self()๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์†ก์‹  ๊ถŒํ•œ์„ ๊ฐ€์ ธ์˜ค๋„๋ก ์ง€์‹œํ•ฉ๋‹ˆ๋‹ค.

์›๊ฒฉ ํฌํŠธ์˜ ๊ฒฝ์šฐ, ๊ณผ์ •์€ ๋ณธ์งˆ์ ์œผ๋กœ ๋ฐ˜๋Œ€๋กœ ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค. ์›๊ฒฉ ์Šค๋ ˆ๋“œ๋Š” mach_reply_port()๋ฅผ ํ†ตํ•ด Mach ํฌํŠธ๋ฅผ ์ƒ์„ฑํ•˜๋„๋ก ์ง€์‹œ๋ฐ›์Šต๋‹ˆ๋‹ค(๋ฐ˜ํ™˜ ๋ฉ”์ปค๋‹ˆ์ฆ˜ ๋•Œ๋ฌธ์— mach_port_allocate()๋Š” ์ ํ•ฉํ•˜์ง€ ์•Š์Œ). ํฌํŠธ๊ฐ€ ์ƒ์„ฑ๋˜๋ฉด, ์›๊ฒฉ ์Šค๋ ˆ๋“œ์—์„œ mach_port_insert_right()๊ฐ€ ํ˜ธ์ถœ๋˜์–ด ์†ก์‹  ๊ถŒํ•œ์ด ์„ค์ •๋ฉ๋‹ˆ๋‹ค. ์ด ๊ถŒํ•œ์€ thread_set_special_port()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ปค๋„์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. ๋กœ์ปฌ ์ž‘์—…์œผ๋กœ ๋Œ์•„๊ฐ€์„œ, thread_get_special_port()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›๊ฒฉ ์ž‘์—…์˜ ์ƒˆ๋กœ ํ• ๋‹น๋œ Mach ํฌํŠธ์— ๋Œ€ํ•œ ์†ก์‹  ๊ถŒํ•œ์„ ํš๋“ํ•ฉ๋‹ˆ๋‹ค.

์ด ๋‹จ๊ณ„๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด Mach ํฌํŠธ๊ฐ€ ์„ค์ •๋˜์–ด ์–‘๋ฐฉํ–ฅ ํ†ต์‹ ์„ ์œ„ํ•œ ๊ธฐ์ดˆ๊ฐ€ ๋งˆ๋ จ๋ฉ๋‹ˆ๋‹ค.

3. Basic Memory Read/Write Primitives

์ด ์„น์…˜์—์„œ๋Š” ๊ธฐ๋ณธ ๋ฉ”๋ชจ๋ฆฌ ์ฝ๊ธฐ/์“ฐ๊ธฐ ์›์‹œ ์ž‘์—…์„ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด ์‹คํ–‰ ์›์‹œ ์ž‘์—…์„ ํ™œ์šฉํ•˜๋Š” ๋ฐ ์ค‘์ ์„ ๋‘ก๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ดˆ๊ธฐ ๋‹จ๊ณ„๋Š” ์›๊ฒฉ ํ”„๋กœ์„ธ์Šค์— ๋Œ€ํ•œ ๋” ๋งŽ์€ ์ œ์–ด๋ฅผ ์–ป๋Š” ๋ฐ ์ค‘์š”ํ•˜์ง€๋งŒ, ์ด ๋‹จ๊ณ„์˜ ์›์‹œ ์ž‘์—…์€ ๋งŽ์€ ์šฉ๋„๋กœ ์‚ฌ์šฉ๋˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ณง ๋” ๊ณ ๊ธ‰ ๋ฒ„์ „์œผ๋กœ ์—…๊ทธ๋ ˆ์ด๋“œ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Memory reading and writing using the execute primitive

๋ชฉํ‘œ๋Š” ํŠน์ • ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”๋ชจ๋ฆฌ ์ฝ๊ธฐ ๋ฐ ์“ฐ๊ธฐ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ์ฝ๊ธฐ:

uint64_t read_func(uint64_t *address) {
return *address;
}

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

void write_func(uint64_t *address, uint64_t value) {
*address = value;
}

์ด ํ•จ์ˆ˜๋“ค์€ ๋‹ค์Œ ์–ด์…ˆ๋ธ”๋ฆฌ์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค:

_read_func:
ldr x0, [x0]
ret
_write_func:
str x1, [x0]
ret

์ ํ•ฉํ•œ ํ•จ์ˆ˜ ์‹๋ณ„

์ผ๋ฐ˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์Šค์บ”ํ•œ ๊ฒฐ๊ณผ ์ด๋Ÿฌํ•œ ์ž‘์—…์— ์ ํ•ฉํ•œ ํ›„๋ณด๊ฐ€ ๋ฐœ๊ฒฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค:

  1. ๋ฉ”๋ชจ๋ฆฌ ์ฝ๊ธฐ โ€” property_getName() (libobjc):
const char *property_getName(objc_property_t prop) {
return prop->name;
}
  1. ๋ฉ”๋ชจ๋ฆฌ ์“ฐ๊ธฐ โ€” _xpc_int64_set_value() (libxpc):
__xpc_int64_set_value:
str x1, [x0, #0x18]
ret

์ž„์˜์˜ ์ฃผ์†Œ์— 64๋น„ํŠธ ์“ฐ๊ธฐ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด:

_xpc_int64_set_value(address - 0x18, value);

์ด๋Ÿฌํ•œ ์›์‹œ ๊ธฐ๋Šฅ์ด ์„ค์ •๋˜๋ฉด, ์›๊ฒฉ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ œ์–ดํ•˜๋Š” ๋ฐ ์žˆ์–ด ์ค‘์š”ํ•œ ์ง„์ „์„ ์ด๋ฃจ๋Š” ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•  ์ค€๋น„๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

4. ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ ์„ค์ •

๋ชฉํ‘œ๋Š” ๋กœ์ปฌ ๋ฐ ์›๊ฒฉ ์ž‘์—… ๊ฐ„์— ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์„ค์ •ํ•˜์—ฌ ๋ฐ์ดํ„ฐ ์ „์†ก์„ ๊ฐ„์†Œํ™”ํ•˜๊ณ  ์—ฌ๋Ÿฌ ์ธ์ˆ˜๋ฅผ ๊ฐ€์ง„ ํ•จ์ˆ˜ ํ˜ธ์ถœ์„ ์šฉ์ดํ•˜๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ์ ‘๊ทผ ๋ฐฉ์‹์€ libxpc์™€ Mach ๋ฉ”๋ชจ๋ฆฌ ํ•ญ๋ชฉ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•๋œ OS_xpc_shmem ๊ฐ์ฒด ์œ ํ˜•์„ ํ™œ์šฉํ•ฉ๋‹ˆ๋‹ค.

ํ”„๋กœ์„ธ์Šค ๊ฐœ์š”

  1. ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น
  • mach_vm_allocate()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ณต์œ ํ•  ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค.
  • ํ• ๋‹น๋œ ์˜์—ญ์— ๋Œ€ํ•ด xpc_shmem_create()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ OS_xpc_shmem ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  1. ์›๊ฒฉ ํ”„๋กœ์„ธ์Šค์—์„œ ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ ์ƒ์„ฑ
  • ์›๊ฒฉ ํ”„๋กœ์„ธ์Šค์—์„œ OS_xpc_shmem ๊ฐ์ฒด๋ฅผ ์œ„ํ•œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค (remote_malloc).
  • ๋กœ์ปฌ ํ…œํ”Œ๋ฆฟ ๊ฐ์ฒด๋ฅผ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค; 0x18 ์˜คํ”„์…‹์—์„œ ๋‚ด์žฅ๋œ Mach ์ „์†ก ๊ถŒํ•œ์˜ ์ˆ˜์ •์ด ์—ฌ์ „ํžˆ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
  1. Mach ๋ฉ”๋ชจ๋ฆฌ ํ•ญ๋ชฉ ์ˆ˜์ •
  • thread_set_special_port()๋กœ ์ „์†ก ๊ถŒํ•œ์„ ์‚ฝ์ž…ํ•˜๊ณ  0x18 ํ•„๋“œ๋ฅผ ์›๊ฒฉ ํ•ญ๋ชฉ์˜ ์ด๋ฆ„์œผ๋กœ ๋ฎ์–ด์”๋‹ˆ๋‹ค.
  1. ์ตœ์ข…ํ™”
  • ์›๊ฒฉ ๊ฐ์ฒด๋ฅผ ๊ฒ€์ฆํ•˜๊ณ  xpc_shmem_remote()์— ๋Œ€ํ•œ ์›๊ฒฉ ํ˜ธ์ถœ๋กœ ๋งคํ•‘ํ•ฉ๋‹ˆ๋‹ค.

5. ์™„์ „ํ•œ ์ œ์–ด ๋‹ฌ์„ฑ

์ž„์˜ ์‹คํ–‰ ๋ฐ ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ ๋ฐฑ ์ฑ„๋„์ด ๊ฐ€๋Šฅํ•ด์ง€๋ฉด, ํšจ๊ณผ์ ์œผ๋กœ ๋Œ€์ƒ ํ”„๋กœ์„ธ์Šค๋ฅผ ์†Œ์œ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค:

  • ์ž„์˜ ๋ฉ”๋ชจ๋ฆฌ R/W โ€” ๋กœ์ปฌ ๋ฐ ๊ณต์œ  ์˜์—ญ ๊ฐ„์— memcpy()๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • 8๊ฐœ ์ด์ƒ์˜ ์ธ์ˆ˜๋ฅผ ๊ฐ€์ง„ ํ•จ์ˆ˜ ํ˜ธ์ถœ โ€” arm64 ํ˜ธ์ถœ ๊ทœ์•ฝ์— ๋”ฐ๋ผ ์Šคํƒ์— ์ถ”๊ฐ€ ์ธ์ˆ˜๋ฅผ ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค.
  • Mach ํฌํŠธ ์ „์†ก โ€” ์„ค์ •๋œ ํฌํŠธ๋ฅผ ํ†ตํ•ด Mach ๋ฉ”์‹œ์ง€์—์„œ ๊ถŒํ•œ์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
  • ํŒŒ์ผ ์„ค๋ช…์ž ์ „์†ก โ€” ํŒŒ์ผ ํฌํŠธ๋ฅผ ํ™œ์šฉํ•ฉ๋‹ˆ๋‹ค (์ฐธ์กฐ: triple_fetch).

์ด ๋ชจ๋“  ๊ฒƒ์€ ์‰ฝ๊ฒŒ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก threadexec ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ํฌ์žฅ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.


6. Apple Silicon (arm64e) ๋‰˜์•™์Šค

Apple Silicon ์žฅ์น˜(arm64e)์—์„œ๋Š” **ํฌ์ธํ„ฐ ์ธ์ฆ ์ฝ”๋“œ(PAC)**๊ฐ€ ๋ชจ๋“  ๋ฐ˜ํ™˜ ์ฃผ์†Œ์™€ ๋งŽ์€ ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๋ฅผ ๋ณดํ˜ธํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์กด ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๋Š” ์Šค๋ ˆ๋“œ ํ•˜์ด์žฌํ‚น ๊ธฐ์ˆ ์€ lr/pc์˜ ์›๋ž˜ ๊ฐ’์ด ์ด๋ฏธ ์œ ํšจํ•œ PAC ์„œ๋ช…์„ ๊ฐ€์ง€๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ณ„์† ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๊ณต๊ฒฉ์ž๊ฐ€ ์ œ์–ดํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ๋กœ ์ ํ”„ํ•˜๋ ค๊ณ  ํ•  ๋•Œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค:

  1. ๋Œ€์ƒ ๋‚ด๋ถ€์— ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค (์›๊ฒฉ mach_vm_allocate + mprotect(PROT_EXEC)).
  2. ํŽ˜์ด๋กœ๋“œ๋ฅผ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค.
  3. ์›๊ฒฉ ํ”„๋กœ์„ธ์Šค ๋‚ด์—์„œ ํฌ์ธํ„ฐ์— ์„œ๋ช…ํ•ฉ๋‹ˆ๋‹ค:
uint64_t ptr = (uint64_t)payload;
ptr = ptrauth_sign_unauthenticated((void*)ptr, ptrauth_key_asia, 0);
  1. ํ•˜์ด์žฌํ‚น๋œ ์Šค๋ ˆ๋“œ ์ƒํƒœ์—์„œ pc = ptr ์„ค์ •.

๋˜๋Š” ๊ธฐ์กด์˜ ๊ฐ€์ ฏ/ํ•จ์ˆ˜๋ฅผ ์—ฐ๊ฒฐํ•˜์—ฌ PAC ์ค€์ˆ˜๋ฅผ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค (์ „ํ†ต์ ์ธ ROP).

7. ํƒ์ง€ ๋ฐ EndpointSecurity๋ฅผ ํ†ตํ•œ ๊ฐ•ํ™”

EndpointSecurity (ES) ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ๋ฐฉ์–ด์ž๊ฐ€ ์Šค๋ ˆ๋“œ ์ฃผ์ž… ์‹œ๋„๋ฅผ ๊ด€์ฐฐํ•˜๊ฑฐ๋‚˜ ์ฐจ๋‹จํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ์ปค๋„ ์ด๋ฒคํŠธ๋ฅผ ๋…ธ์ถœํ•ฉ๋‹ˆ๋‹ค:

  • ES_EVENT_TYPE_AUTH_GET_TASK โ€“ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋‹ค๋ฅธ ์ž‘์—…์˜ ํฌํŠธ๋ฅผ ์š”์ฒญํ•  ๋•Œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค (์˜ˆ: task_for_pid()).
  • ES_EVENT_TYPE_NOTIFY_REMOTE_THREAD_CREATE โ€“ ๋‹ค๋ฅธ ์ž‘์—…์—์„œ ์Šค๋ ˆ๋“œ๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ๋งˆ๋‹ค ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
  • ES_EVENT_TYPE_NOTIFY_THREAD_SET_STATE (macOS 14 Sonoma์— ์ถ”๊ฐ€๋จ) โ€“ ๊ธฐ์กด ์Šค๋ ˆ๋“œ์˜ ๋ ˆ์ง€์Šคํ„ฐ ์กฐ์ž‘์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

์›๊ฒฉ ์Šค๋ ˆ๋“œ ์ด๋ฒคํŠธ๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ์ตœ์†Œํ•œ์˜ Swift ํด๋ผ์ด์–ธํŠธ:

import EndpointSecurity

let client = try! ESClient(subscriptions: [.notifyRemoteThreadCreate]) {
(_, msg) in
if let evt = msg.remoteThreadCreate {
print("[ALERT] remote thread in pid \(evt.target.pid) by pid \(evt.thread.pid)")
}
}
RunLoop.main.run()

osquery โ‰ฅ 5.8๋กœ ์ฟผ๋ฆฌํ•˜๊ธฐ:

SELECT target_pid, source_pid, target_path
FROM es_process_events
WHERE event_type = 'REMOTE_THREAD_CREATE';

Hardened-runtime considerations

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ com.apple.security.get-task-allow ๊ถŒํ•œ ์—†์ด ๋ฐฐํฌํ•˜๋ฉด ๋น„๋ฃจํŠธ ๊ณต๊ฒฉ์ž๊ฐ€ ํ•ด๋‹น ์ž‘์—… ํฌํŠธ๋ฅผ ์–ป๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‹œ์Šคํ…œ ๋ฌด๊ฒฐ์„ฑ ๋ณดํ˜ธ(SIP)๋Š” ์—ฌ์ „ํžˆ ๋งŽ์€ Apple ๋ฐ”์ด๋„ˆ์Šค์— ๋Œ€ํ•œ ์ ‘๊ทผ์„ ์ฐจ๋‹จํ•˜์ง€๋งŒ, ์„œ๋“œํŒŒํ‹ฐ ์†Œํ”„ํŠธ์›จ์–ด๋Š” ๋ช…์‹œ์ ์œผ๋กœ ์˜ตํŠธ์•„์›ƒํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

8. Recent Public Tooling (2023-2025)

ToolYearRemarks
task_vaccine2023Ventura/Sonoma์—์„œ PAC ์ธ์‹ ์Šค๋ ˆ๋“œ ํ•˜์ด์žฌํ‚น์„ ๋ณด์—ฌ์ฃผ๋Š” ๊ฐ„๊ฒฐํ•œ PoC
remote_thread_es2024์—ฌ๋Ÿฌ EDR ๊ณต๊ธ‰์ž๊ฐ€ REMOTE_THREAD_CREATE ์ด๋ฒคํŠธ๋ฅผ ํ‘œ์ถœํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•˜๋Š” EndpointSecurity ํ—ฌํผ

์ด๋Ÿฌํ•œ ํ”„๋กœ์ ํŠธ์˜ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ์ฝ๋Š” ๊ฒƒ์€ macOS 13/14์—์„œ ๋„์ž…๋œ API ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ดํ•ดํ•˜๊ณ  Intel โ†” Apple Silicon ๊ฐ„์˜ ํ˜ธํ™˜์„ฑ์„ ์œ ์ง€ํ•˜๋Š” ๋ฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

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 ์ง€์›ํ•˜๊ธฐ