-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathgolconde.asm
305 lines (268 loc) · 5.89 KB
/
golconde.asm
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
section .data
httpRequest db "GET /wget HTTP/1.1",0xD,0xA
db "Host: %s:%s",0xD,0xA
db "Connection: close",0xD,0xA,0xD,0xA
fileName db "wget",0
usage_msg db "Usage: %s <ip> <port>",0xA,0
error_ip db "Invalid IP address",0xA,0
error_port db "Invalid port number",0xA,0
section .bss
sockaddr resb 16
recvBuffer resb 16384
fd resb 4
ip_str resb 16 ; IP地址缓冲区
port_str resb 6 ; 端口缓冲区
formatted_request resb 512 ; 格式化后的HTTP请求缓冲区
section .text
global _start
_start:
; 检查命令行参数
pop rax ; 获取参数个数
cmp rax, 3 ; 需要3个参数
jne usage_error
pop rax ; 程序名
pop rax ; IP地址
mov r14, rax ; 保存IP地址
pop rax ; 端口
mov r15, rax ; 保存端口
; 复制IP和端口到缓冲区
mov rsi, r14
mov rdi, ip_str
call strcpy
mov rsi, r15
mov rdi, port_str
call strcpy
; 检查端口号有效性
mov rdi, port_str
call validate_port
test rax, rax
jz port_error
; 检查IP地址有效性
mov rdi, ip_str
call validate_ip
test rax, rax
jz ip_error
; 创建socket
mov rax, 41 ; socket syscall
mov rdi, 2 ; AF_INET
mov rsi, 1 ; SOCK_STREAM
xor rdx, rdx ; 0
syscall
mov r12, rax ; 保存socket fd
; 设置sockaddr结构
mov word [sockaddr], 2 ; AF_INET
; 转换端口号
mov rdi, port_str
call atoi
xchg al, ah ; 转换为网络字节序
mov word [sockaddr+2], ax ; 设置端口
; 转换IP地址
mov rdi, ip_str
mov rsi, sockaddr+4
call inet_pton
xor rax, rax
mov qword [sockaddr+8], rax
; 连接到服务器
mov rax, 42 ; connect syscall
mov rdi, r12 ; socket fd
mov rsi, sockaddr ; struct sockaddr *
mov rdx, 16 ; addrlen
syscall
; 发送HTTP请求
mov rax, 44 ; sendto syscall
mov rdi, r12 ; socket fd
mov rsi, httpRequest ; message
mov rdx, 512 ; length
xor r10, r10 ; flags
xor r8, r8 ; dest_addr
xor r9, r9 ; addrlen
syscall
; 打开文件准备写入
mov rax, 2 ; open syscall
mov rdi, fileName ; filename
mov rsi, 0102o ; O_CREAT|O_WRONLY
mov rdx, 0644o ; mode
syscall
mov r13, rax ; 保存文件fd
xor r14, r14 ; r14用于标记是否找到header
read_loop:
mov rax, 0 ; read syscall
mov rdi, r12 ; socket fd
mov rsi, recvBuffer ; buffer
mov rdx, 16384 ; count
syscall
test rax, rax
jle cleanup
mov r15, rax ; 保存读取的长度
test r14, r14
jnz write_data
find_header:
mov rcx, recvBuffer
mov rdx, rcx
add rdx, r15
next_byte:
cmp rcx, rdx
jge read_loop
cmp dword [rcx], 0x0A0D0A0D
je header_found
inc rcx
jmp next_byte
header_found:
mov r14, 1
add rcx, 4
mov rsi, rcx
mov rdx, recvBuffer
add rdx, r15
sub rdx, rcx
jmp write_file
write_data:
mov rsi, recvBuffer
mov rdx, r15
write_file:
mov rax, 1 ; write syscall
mov rdi, r13 ; file fd
syscall
jmp read_loop
cleanup:
mov rax, 3 ; close syscall
mov rdi, r13 ; file fd
syscall
mov rax, 3 ; close syscall
mov rdi, r12 ; socket fd
syscall
mov rax, 60 ; exit syscall
xor rdi, rdi
syscall
usage_error:
mov rdi, 1
mov rsi, usage_msg
mov rdx, 26
mov rax, 1 ; write syscall
syscall
mov rax, 60 ; exit syscall
mov rdi, 1
syscall
ip_error:
mov rdi, 1
mov rsi, error_ip
mov rdx, 18
mov rax, 1 ; write syscall
syscall
mov rax, 60 ; exit syscall
mov rdi, 1
syscall
port_error:
mov rdi, 1
mov rsi, error_port
mov rdx, 19
mov rax, 1 ; write syscall
syscall
mov rax, 60 ; exit syscall
mov rdi, 1
syscall
; 辅助函数
strcpy: ; rdi = destination, rsi = source
xor rcx, rcx
.loop:
mov al, [rsi + rcx]
mov [rdi + rcx], al
inc rcx
test al, al
jnz .loop
ret
atoi: ; rdi = string
xor rax, rax
xor rcx, rcx
.loop:
movzx rdx, byte [rdi + rcx]
test rdx, rdx
jz .done
sub rdx, '0'
imul rax, 10
add rax, rdx
inc rcx
jmp .loop
.done:
ret
inet_pton: ; rdi = IP string, rsi = destination
xor rax, rax
xor rcx, rcx
xor rdx, rdx
.loop:
movzx r8, byte [rdi + rcx]
test r8, r8
jz .done
cmp r8, '.'
je .next_octet
sub r8, '0'
imul rdx, 10
add rdx, r8
inc rcx
jmp .loop
.next_octet:
mov byte [rsi], dl
inc rsi
xor rdx, rdx
inc rcx
jmp .loop
.done:
mov byte [rsi], dl
ret
validate_port: ; rdi = port string
xor rax, rax
xor rcx, rcx
xor rdx, rdx
.loop:
movzx r8, byte [rdi + rcx]
test r8, r8
jz .check_value
sub r8, '0'
cmp r8, 9
ja .error
imul rdx, 10
add rdx, r8
inc rcx
jmp .loop
.check_value:
cmp rdx, 65535
ja .error
mov rax, 1
ret
.error:
xor rax, rax
ret
validate_ip: ; rdi = IP string
xor rax, rax
xor rcx, rcx
xor rdx, rdx
mov r9, 0 ; 点的数量
.loop:
movzx r8, byte [rdi + rcx]
test r8, r8
jz .check_dots
cmp r8, '.'
je .check_octet
sub r8, '0'
cmp r8, 9
ja .error
imul rdx, 10
add rdx, r8
inc rcx
jmp .loop
.check_octet:
cmp rdx, 255
ja .error
inc r9
xor rdx, rdx
inc rcx
jmp .loop
.check_dots:
cmp r9, 3
jne .error
cmp rdx, 255
ja .error
mov rax, 1
ret
.error:
xor rax, rax
ret