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
|
global _start
%macro write 3
mov rdi, %1
mov rsi, %2
mov rdx, %3
mov rax, 1
syscall
%endmacro
%macro read 3
mov rdi, %1
mov rsi, %2
mov rdx, %3
xor rax, rax
syscall
%endmacro
%macro mmap 6
mov rdi, %1
mov rsi, %2
mov rdx, %3
mov r10, %4
mov r8, %5
mov r9, %6
mov rax, 9
syscall
%endmacro
%macro munmap 2
mov rdi, %1
mov rsi, %2
mov rax, 11
syscall
%endmacro
%macro exit 1
mov rdi, %1
mov rax, 60
syscall
%endmacro
section .text
_start:
pop qword [argc]
pop rcx
cmp dword [argc], 1
jg skip_stdin
stdin_loop:
read 0, buf, 4000
cmp rax, 1
jle end
mov rdx, buf
mov rcx, [argc]
jmp count_start
clear_pos:
cmp rbx, rax
je arg_loop
mov byte [pos + rax], 0
inc rax
jmp clear_pos
skip_stdin:
mov rcx, [argc]
arg_loop:
cmp rcx, 1
jle end
pop rdx
count_start:
xor rax, rax
xor rbx, rbx
count_loop:
cmp byte [rdx + rax], '~'
je found
cmp byte [rdx + rax], '`'
je found
cmp byte [rdx + rax], '_'
je found
cmp byte [rdx + rax], '*'
je found
cmp byte [rdx + rax], '|'
je found
cmp byte [rdx + rax], '\'
je found
cmp byte [rdx + rax], 0
je escape
inc rax
jmp count_loop
found:
inc rbx
mov byte [pos + rax], 1
inc rax
jmp count_loop
escape:
push rcx ; argc counter
push rax ; string length
push rbx ; number of extra characters needed
push rdx ; string memory address
add rbx, rax
inc rbx
mmap 0, rbx, 3, 34, -1, 0 ; 3 = PROT_READ | PROT_WRITE, 34 = MAP_PRIVATE | MAP_ANONYMOUS
pop rdx
pop rbx
pop rsi
add rsi, rbx
xor r8, r8
xor r9, r9
escape_loop:
cmp r9, rsi
je escape_loop_end
cmp byte [pos + r8], 1
jne skip_backslash
mov byte [rax + r9], '\'
inc r9
skip_backslash:
mov r10b, byte [rdx + r8]
mov byte [rax + r9], r10b
inc r8
inc r9
jmp escape_loop
escape_loop_end:
mov byte [rax + r9], 10
inc r9
push rax
write 1, rax, r9
pop rax
munmap rax, r9
pop rcx
next_arg:
dec rcx
xor rax, rax
jmp clear_pos
end:
exit 0
section .bss
argc: resq 1
buf: resb 4001
pos: resb 4000
|