
애드혹 온더플라이 프로토콜 생성을 위한 인메모리 최소 CPU
Harald는 인메모리 방식의 소형 고수준 CPU로, 주어진 네트워크 프로토콜(TCP/UDP) 상에서 사용될 애플리케이션 계층 프로토콜을 생성하기 위한 명령어 집합을 처리할 수 있습니다.
Harald는 OPCODE 스트림을 소비하고, 정의된 애플리케이션 계층 프로토콜에 적합하도록 페이로드에 다양한 변환을 적용합니다.
[!TIP] 왜 _Harald_일까요? 덴마크의 왕 Harald Gormsson은 그의 별명인 Blátǫnn, 즉 오늘날 우리가 발음하는 Bluetooth로 유명합니다. 이 기술은 당시 Harald가 덴마크와 바이킹 왕국을 _연결_했기 때문에 그의 별명을 따서 명명되었습니다. 그래서 저는 그의 이름(firstname)을 따서 이것을 명명했습니다.
Harald는 CPU처럼 동작합니다. 이는 동작을 정의하는 OPCODE 집합을 따릅니다. 즉, PROTOCOL입니다. Harald는 필요한 프로토콜을 즉석에서 생성하기 위해 요구되는 연산을 처리합니다.
PROTOCOL이 제공되면, Harald는 전송할 PAYLOAD를 순회하면서 각 프래그먼트마다 전체 PROTOCOL을 한 번씩 실행합니다. 즉, 페이로드를 여러 프래그먼트로 분할해야 하는 경우, Harald는 모든 프래그먼트에 동일한 프로토콜을 사용하여 현재 페이로드 프래그먼트에 대해 프로토콜에 정의된 모든 동작을 실행합니다.
Harald는 프로토콜이 값을 저장하는 데 사용할 수 있는 여러 레지스트리를 보유합니다. 이러한 레지스트리는 덧셈, 뺄셈, 인코딩 및 디코딩 등 여러 연산을 수행하는 데 사용할 수 있습니다.
Harald는 페이로드 프래그먼트를 전송할 때 수행되는 각 요청에 대한 응답을 프로토콜이 저장할 수 있도록 결과 배열을 동적으로 할당합니다.

Harald는 프로토콜로 제공될 다양한 Opcode를 지원합니다. Harald는 주어진 Opcode를 수신하면 일련의 고수준 연산을 수행합니다. 각 Opcode는 미리 정의된 길이의 미리 정의된 인수 집합을 기대합니다.
| OPCODE::Nº | Description | ARGS::Size |
|---|---|---|
| H_F_APPEND::0x01 | Appends the following N Bytes to the end payload | Size::4, NBytes::N |
| H_F_PREPEND::0x02 | Prepends the following N Bytes to the end payload | Size::4, NBytes::N |
| H_F_SPLIT::0x03 | Splits the Payload in fragments of the given size | Size::4 |
| H_F_PAYLOAD_INJECT::0x04 | Injects the Payload fragment into the End Payload | - |
| H_F_SOCK_INIT::0x05 | Initializes the socket connection | IsIPAddress:1, SSL_Enabled::1, TCP/UDP::1, [(HostLen::4,HostName:N)/IPAddress::4], Port::2 |
| H_F_SEND::0x06 | Sends the constructed End Payload | - |
| H_F_RECV::0x07 | Receives up to N Bytes | Size::4 |
| H_F_CLOSE::0x08 | Closes the socket and cleans | - |
| H_F_INJECT::0x09 | Injects the requested registry into the End Payload | Reg::1 |
| H_F_ENCODE_STR::0x0A | Encodes a Payload field to its string representation | IsReg::1, [(Payload::1, Field::1)/Reg::1], Format::1 |
| H_F_DECODE_STR::0xA0 | Decodes the contents of a registry to its numeric representation | Reg::1 |
| H_F_ENCODE_STRB64::0x0B | Encodes a Payload field to its B64string representation | Payload::1, Field::1 |
| H_F_COMPUTE_FRAG_LENGTH::0x0D | Calculates the next fragment to be sent length | - |
| H_F_SEARCH::0x0E | Searches for a given byte pattern of a given N size in a given registry | Reg::1, Size::4, NBytes::N |
| H_F_SEEK::0x0F | Moves the cursor in a given payload by a given number of bytes | Payload::1, Offset::4 |
| H_F_PUSH::0x10 | Pushes a number of bytes or the contents of a registry into another registry | IsReg::1, [Size::4, NBytes::N]/SrcReg::1, DstReg::2 |
| H_F_ADD::0x12 | Adds two registries or a number to a registry | IsReg::1, [Size::4, NBytes::N]/SrcReg::1, DstReg::2 |
| H_F_SUBSTRACT::0x13 | Substracts two registries or a number to a registry | IsReg::1, [Size::4, NBytes::N]/SrcReg::1, DstReg::2 |
| H_F_READ::0x14 | Reads from a given registry up to the length stored in another registry | FromReg::1, SizeReg::1 |
| H_F_STORE::0x15 | Stores a registry value into Harald's Storage | Reg::1 |
다음 Opcode 스트림은 통신이 HTTP로 이해되도록 전송에 필요한 데이터를 생성합니다. 이는 연결을 시작하고, 페이로드를 HTTP 트래픽처럼 보이도록 수정하며, SSL/TLS 연결을 통해 전송하고, 마지막에 연결을 닫습니다.
H_F_SPLIT, 0x00, 0x00, 0x00, 0xFF, // Splits the Payload
H_F_APPEND, 0x00, 0x00, 0x00, 0x46, // Appends...
'P', 'O', 'S', 'T', ' ', '/', ' ', // POST /
'H', 'T', 'T', 'P', '/', '1', '.', '1', '\r', '\n', // HTTP/1.1
'H', 'o', 's', 't', ':', ' ', // Host:
'd', 'o', 'm', 'a', 'i', 'n', '.', 'c', 'o', 'm', '\r', '\n', // domain.com
'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', ':', ' ', // Connection:
'c', 'l', 'o', 's', 'e', '\r', '\n', // close
'C', 'o', 'n', 't', 'e', 'n', 't', '-', // Content-
'L', 'e', 'n', 'g', 't', 'h', ':', ' ', // Length:
H_F_COMPUTE_FRAG_LENGTH, // Next Fragment's size
H_F_ENCODE_STR, H_PAY_END_PAYLOAD, H_PAY_FRAGMENT_SIZE, 'u', // FragSize encode
H_F_INJECT, H_REG_RET, // Inject the Fragment Size encoded str
H_F_APPEND, 0x00, 0x00, 0x00, 0x04, '\r', '\n', '\r', '\n', // Append Body begin
H_F_PAYLOAD_INJECT, // Inject the Payload
H_F_SOCK_INIT, 0x01, 0x01, 0x7F, 0x00, 0x00, 0x01, 0x04, 0xD2, // Init Socket
H_F_SEND, // Send the Payload over the socket
H_F_CLOSE // Close the socket and cleanup
다음 예제는 이전 예제와 동일한 절차를 따릅니다. 그러나 페이로드를 단순히 본문으로 전송하는 대신, 프로토콜은 Harald에게 몇 가지 헤더를 설정하고 본문을 구성하여 GitHub API와 통신해 비공개 저장소의 이슈에 댓글을 게시할 수 있도록 지시합니다.
이러한 종류의 통신은 공격자가 *.github.com과 같은 신뢰할 수 있는 도메인을 사용하여 C2 서버와 통신 채널을 만드는 데 도움이 될 수 있습니다. 바로 이 예제는 AWS 리소스(sqs..amazonaws.com 아래의 SQS 큐 등), Azure 리소스(<storage_account_name>.blob.core.windows.net 아래의 blob 등)를 사용하도록 확장할 수도 있습니다.
이 예제는 STRUCTURED_FORMAT(JSON) + APPLICATION-LAYER_PROTOL(HTTPS) + PROTOCOL(TCP)을 요구하는 통신에 좋은 참고 자료입니다.