forked from CoolerVoid/C
-
Notifications
You must be signed in to change notification settings - Fork 0
/
asm_tuto.txt
374 lines (321 loc) · 11.1 KB
/
asm_tuto.txt
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
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
Anos que digo para mim que vou escrever algo de "Assembly" vai ano e passa, acabo deixando
de lado, já algum tempo ando estudando fazendo coisas simples bem devagar, isso tem me ajudado a depurar meus programas em linguagem C, claro que também me ajuda nos skills de hacking seja com engenharia reversa ou para entender problemas que tenham overflow, programar para um microcontrolador etc...
Se assembly fosse banda seria uma banda de heavy metal... rsrs
Se assembly fosse banda seria uma banda de heavy metal... rsrs
Antes de começar queria agradecer de coração "sigsegv","m0nad","iak","kov","__i","MySoft","muzgo"
por terem me influenciado em Assembly e ter me ajudado por muitas vezes e até hoje...
irc.freenode.net nos canais #asm,#c-br,#lisp-br,#cogubin.
"antes que me esqueça feliz pascoa caros leitores desse blog..."
Em "Assembly" tem duas sintaxes "AT&T" e o "Intel" a pouco
tempo só usava "Intel", mas como minha intenção é só usar
assembly dentro da "linguagem C" tive problemas com sintaxe
intel, mesmo convertendo etc bugs bizarros com input, então
nunca gostei do "nasm" também,parti para o GAS e só estou
usando "AT&T" agora. Nos muitos livros que li só tinha
introdução básica, e sempre estava como linguagem de montagem
e não como "Assembly" , não acho legal traduzir isso , o
que anda me ajudando mesmo é ler o "programming from the ground up"
do Jonathan Bartlett.
Galera tem muito medo de "Assembly", eu achava que só os
JEDI SITH podiam codar em "Assembly", hoje eu acho fácil
claro que se eu tiver com uma tabela dos registradores e dos
"JMP" etc...
Um registrador em Assembly é uma área de memoria
que referência um determinado circuito do processador.
olhe estas tabelas , caso queira
codar com shellcodes leiam paper do meu amigo m0nad do cogumelo binario
Algo para ajudar um texto do meu amigo IAK http://code.google.com/p/bugsec/wiki/AssemblyArqComp
bom tabelas dos registradores,syscalls,aritmética,jmp,access types
vou passando no decorrer do "post", não é minha ideia ensinar
"Assembly" mesmo porque sou noob, ideia é mostrar como usar em
"linguagem C".
vamos la... para tirar a ferrugem um "ola"
[sourcecode language="c"]
# exemplo chamando exit() e write()
.section .data
output:
.ascii "Ola.\n"
output_end:
.equ len, output_end - output
.section .text
.globl _start
_start:
# mov com "l" significa que vamos usar 32bit vide tabela
# eax deixamos o número do syscall que seria 4
movl $4, %eax
# $ cat unistd_32.h | grep write
# define __NR_write 4 <-- num do syscall
# número do descriptor 1 para out no primeiro argumento
movl $1, %ebx
# nossa string no segundo argumento
movl $output, %ecx
# tamanho da string no terceiro argumento
movl $len, %edx
# executa write(1,string,len);
int $0x80
# exit()
movl $1, %eax
# exit(0);
movl $0, %ebx
# executa o exit() fecha...
int $0x80
[/sourcecode]
compilamos,linkamos e executamos
$ as code.s -o code.o
$ ld code.o -o code
$ ./code
ola.
$
OK , para entender a ordem dos registradores na hora de passar
argumentos para um syscall, vejamos se esta tabela pode ajudar
Ao passar argumento para um syscall
[sourcecode language="c"]
EBX primeiro parametro
ECX segundo parametro
EDX terceiro parametro
ESI quarto parametro
EDI quinto parametro
[/sourcecode]
se você não entendeu o "movl"
Aritmética básica
[sourcecode language="c"]
Adição: ADD, ADC, INC, XADD, AAA e DAA;
Subtracção: SUB, SBB, DEC, AAS e DAS;
Multiplicação: MUL, IMUL e AAM;
Divisão: DIV, IDIV e AAD.
Atribuição: MOV
[/sourcecode]
por que ? "l"
[sourcecode language="c"]
b = byte (8 bit)
s = short (16 bit integer) or single (32-bit floating point)
w = word (16 bit)
l = long (32 bit integer or 64-bit floating point)
q = quad (64 bit)
t = ten bytes (80-bit floating point)
[/sourcecode]
OK agora sabemos aritmética básica vamos fazer uma
função em Assembly que calcula o cubo de um número,
para assim poder usar na linguagem C
$ vim cubo.s
[sourcecode language="c"]
# função calcula cubo(int x), retorna result int...
# gcc -o code code.c cubo.s
.type cubo, @function
.globl cubo
cubo:
# pegamos o extended base pointer para pegar argumentos
pushl %ebp
# movemos extented stack pointer para %ebp
movl %esp, %ebp
# passamos primeiro argumento da função para %eax
movl 8(%ebp), %eax
# multiplicamos eax por eax
imull %eax, %eax
# passamos o primeiro argumento para %edx
movl 8(%ebp), %edx
#multiplicamos por eax
imull %edx , %eax
# damos return no resultado
movl %ebp, %esp
popl %ebp
ret
[/sourcecode]
vamos la então
$ vim test.c
[sourcecode language="c"]
#include <stdio.h>
int main()
{
printf("%d \n",cubo(6));
return 0;
}
[/sourcecode]
compilamos e executamos
$ gcc -o test test.c test.s
$ ./test
216
$
tudo OK !
agora como usar assembly dentro do nosso código
vamos ver como fazer nosso Inline Assembly
[sourcecode language="c"]
/*
* agradeço ao amigo __i da freenode do ##C-br
por ter me ajudado neste exemplo...
*/
#include <stdio.h>
int
add(int x, int y)
{
int a = 0;
// poderia ser asm() ou __asm__() ...
__asm__(
// primeiro argumento para edx
"movl 8(%ebp), %edx\n"
// segundo argumento para eax
"movl 12(%ebp), %eax\n"
// soma os dois e fica em eax
"addl %edx, %eax\n"
// movemos para var "a",
// se tive-se segunda var como "b" fariamos -8(%ebp)
"mov %eax, -4(%ebp)\n"
);
return a;
}
int
main(void)
{
printf("%d\n", add(3,2));
return 0;
}
[/sourcecode]
$ gcc -m32 -o code code.c; ./code
5
$
usamos argumento -m32 para usar 32bit
seguindo esse exemplo eu fiz uma calculadora simples
Agora um exemplo de Extended Assembly , vamos fazer
uma simples condição.
$ vim test.c
[sourcecode language="c"]
#include <stdio.h>
int main()
{
int a = 3;
int b = 51;
int result;
// jle jump if less
asm(
// compara "a" e "b"
"cmp %1, %2\n\t"
// se for menor pula para o label LESS
"jl LESS\n\t"
// result recebe "a"
"movl %1, %0\n\t"
// pula para o fim
"jmp end\n"
"LESS:\n\t"
// result recebe "b"
"movl %2, %0\n"
"end:"
// passamos os input
:"=r"(result)
:"r"(a), "r"(b)
);
printf("valor menor é %d\n", result);
return 0;
}
[/sourcecode]
$ gcc -m32 -o code code.c; ./code
valor menor é 3
$
não gosto de usar extended vou deixar uma url
para quem quiser se aprofundar AQUI
Assim eu fiz uma tabela humilde com alguns JMP
[sourcecode language="c"]
+-------------------+----------------------------+-------------------------------+
| ASSEMBLY | inglês | tradução |
+-------------------+----------------------------+-------------------------------+
| ja / jnbe <label> | Above / Not below or equal | acima/não abaixo ou igual |
+-------------------+----------------------------+-------------------------------+
| jae / jnb <label> | Above or equal / Not below | acima ou igual / não menor |
+-------------------+------------------------------------------------------------+
| jb / jnae <label> | Below / Not above or equal | abaixo / não acima ou igual |
+-------------------+------------------------------------------------------------+
| jc <label> | Carry | carrega |
+-------------------+------------------------------------------------------------+
| je/jz <label> | Equal / Zero | igual / zero |
+-------------------+------------------------------------------------------------+
| jnc <label> | Not Carry | não carrega |
+-------------------+------------------------------------------------------------+
| jne/jnz <label> | Not Equal / Not Zero | não igual / não zero |
+--------------------------------------------------------------------------------+
| jg / jnle <label> | Greater / Not Less or Equal | maior / não menor ou igual |
+--------------------------------------------------------------------------------+
| jge / jnl <label> | Greater or Equal / Not Less | maior ou igual / não menor |
+--------------------------------------------------------------------------------+
| jl / jnge <label> | Less / Not Greater or Equal | menor / não maior ou igual |
+--------------------------------------------------------------------------------+
| jle / jng <label> | Less or Equal / Not Greater | menor ou igual / não maior |
+--------------------------------------------------------------------------------+
| jno <label> | Not overflow
+----------------------------------------------------------------------------+
| jns <label> | Not sign (non-negative)
+----------------------------------------------------------------------------+
| jo <label> | Overflow
+----------------------------------------------------------------------------+
| js <label> | Sign (negative)
+-------------------+--------------------------------------------------------+
[/sourcecode]
vamos agora um exemplo mais ZEN, vamos fazer uma
função em C com inline ASM para escrever em um arquivo.
Antes de codar vamos olhar tabela de access type
[sourcecode language="c"]
O_RDONLY 00 - Open the file for read-only access.
O_WRONLY 01 - Open the file for write-only access.
O_RDWR 02 - Open the file for both read and write access.
O_CREAT 0100 - Create the file if it does not exist.
O_EXCL 0200 - When used with O_CREAT, if the file exists, do not open it.
O_TRUNC 01000 If the file exists and is open in write mode, truncate it to a
length of zero.
O_APPEND 02000 - Append data to the end of the file.
O_NONBLOCK 04000 - Open the file in nonblocking mode.
O_SYNC 010000 - Open the file in synchronous mode (allow only one write
at a time).
O_ASYNC 020000 - Open the file in asynchronous mode (allow multiple
writes at a time).
[/sourcecode]
então vamos usar
1001 == O_WRONLY | O_CREAT
$ vim writefile.c
[sourcecode language="c"]
#include <stdio.h>
void
writefile(char *filename,char *msg,int msglen)
{
__asm__(
// syscall open("string", O_CREAT | O_WRONLY, 0644);
"movl $0x05, %eax\n"
// nosso primeiro argumento
"movl 8(%ebp), %ebx\n"
// O_CREAT | O_WRONLY
"movl $1001, %ecx\n"
// aqui você já sabe permissões em octal do unix
"movl $0644, %edx\n"
"int $0x80\n"
// fd esta em %eax do open(), movemos para o %ebx para o write()
"movl %eax, %ebx\n"
// syscall write(fd, message, messageLen);
"movl $0x04, %eax\n"
// fd em %ebx para acima
// segundo argumento
"movl 12(%ebp), %ecx\n"
// 12+4 terceiro argumento nosso
"movl 16(%ebp), %edx\n"
"int $0x80\n"
// syscall close(fd);
"movl $0x06, %eax\n"
// fd still in %ebx
"int $0x80\n"
);
}
int main()
{
writefile("ola3.txt","lol",3);
return 0;
}
[/sourcecode]
$ gcc -o writefile writefile.c; ./writefile; cat ola.txt
lol
$
OK foi como esperado
Bom caros leitores, tem muito mais o que estudar com Inline Assembly,
espero que fiquem com um bloco do chocolate para quem sabe um dia
conseguir comer o chocolate todo. é com exemplos simples que se consegue
dar passos mais largos. ;-)
sugiro que leiam este post antigo de kernel,syscall...
algumas referências:
http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
http://asm.sourceforge.net/articles/rmiyagi-inline-asm.txt
aloha o/