Lesson 6


TIME TO CODE





A importância da programação

Você deve entender o quão importante é saber como programar. Na área de segurança, você vai encarar diferentes tipos de softwares escrito em tipos muito diferentes de linguagens de programação. Você pode encontrar uma aplicação escrita em PHP, Java, Python, C e muitos outros. Para encontrar vulnerabilidades nesses aplicativos, você deve conhecer os conceitos internos de cada uma delas, além de ser capaz de ler e entender o que eles foram programados para fazer. É assim que você vai encontrar várias falhas lógicas que os programadores costumam cometer no uso indevido dessas linguagens.

Além disso, grande parte das tarefas que você fará serão repetitivas. Ou você terá que fazê-las com frequência, ou são muito cansativas de fazer manualmente. É aí que a automação entra. Às vezes você vai querer escrever scripts para facilitar sua vida, vai precisar escrever exploits complexos que lhe darão um shell, ou entender para modificar um exploit que achou na internet.

Esta lição será bem básica, e não entrará em detalhes especiais. Apenas lhe dará uma ideia geral sobre programação. Enquanto nós aprendemos, vamos resolver um desafio muito simples.

Nosso Desafio: Somar os números ímpares menores que 1000.

Algoritimos

Algorítimos são a base da programação. Aprender como construí-los é a primeira coisa para começar antes de sujar as mãos com código.

“Informalmente, um algoritmo é qualquer procedimento computacional bem definido que leva algum valor ou conjunto de valores, como entrada e produz algum valor, ou conjunto de valores, como saída. Um algoritmo é, portanto, uma sequência de etapas computacionais que transformam a entrada na saída. Também podemos visualizar um algoritmo como uma ferramenta para resolver um cálculo computacional bem especificado.” [1]

Sempre que você enfrenta uma tarefa que precisa escrever um código, o primeiro passo é colocar o algoritmo em conjunto. Depois disso, deve ser simples expressar seu algoritmo em qualquer linguagem de programação que você deseja, você precisará entender sua sintaxe e semântica desse idioma.

Vamos ver como seria o algoritmo para o nosso desafio:

1. Para cada número menor que 1000
2. Verificar se o número é ímpar.
3. Se sim, some aos outros.
4. Imprima os resultados.

Ambiente de Programação

Para começar a programar, tudo que você precisa é um editor de texto. Se você estiver usando Windows: Notepad, Notepad++, Sublime são ótimas opções, entre muitas outras. Se você estiver no Linux. Se você está no Linux, existem como opçoes o VIM, Emacs, Nano, GeditGeany, Kate, e a maioria deles já vem pré-instalados no sistema. Escolha o que você se sentir mais confortável.

Também existem ferramentas chamadas de Integrated Development Environment, comumente chamadas de IDEs. Essas ferramentas são criadas para tornar a tarefa de programar mais fácil, completando palavras e funções, destacando seus erros, sugerindo alterações e às vezes facilitando a execução e teste seu código.

Recomendamos fortemente que você não comece a programar com IDEs. Elas tornam sua vida tão fácil, que você pode não aprender exatamente como fazer ou não entender algumas coisas. A funcionalidade de autocompletar também o tornará dependente e você não lembrará o nome dos métodos e funções quando precisar e não tiver uma IDE para ajudá-lo.

Compilado ou Interpretado?

Você sabe que os computadores só entendem 0s e 1s, mas quando escrevemos código, usamos linguagens de mais alto nível, ou seja, usamos um idioma que pode ser facilmente lido por um ser humano, mas não por um computador. Então, depois de terminar de escrever nosso código, devemos transformar o código que escrevemos para algo que pode ser facilmente interpretado por um computador. De modo geral, há pelo menos duas maneiras diferentes que podem ser feitas.

Você está acostumado ver os arquivos .EXE no Windows e os arquivos ELF no Linux. Esses arquivos são exemplos de códigos compilados. Um código-fonte, que é o código que foi escrito pelo programador, passou por um processo que o tornou legível por um computador. Esse processo é chamado de 'Compilação'. Então, dizemos que esse é um código compilado.

Linguagens de script como Bash, Python, Ruby não precisam ser compiladas. Para executar o código que escrevemos, usamos o que é chamado de interpretador. O interpretador lê e transforma seu código linha por linha, desde o início até o fim sequencialmente. Isso significa que seu código se tornará legível pelo computador apenas no momento em que você estiver executando, e isso pode tornar seu código mais lento do que os códigos compilados. Além disso, você deve ter em mente que diferente do código compilado, antes de chegar à próxima linha, o intérprete não sabe o que está por vir, o que interfere diretamente na forma que você programa.

No Linux, nós usaremos um compilador chamado GCC. No Windows, utilizaremos o MinGW. No Linux, o GCC já vem instalado por padrão. A instalação do MingGW não será abordada nesta lição.



Nota: Todos os exemplos desta lição serão executados no Linux.

Abra um editor de texto de sua escolha e escreva o seguinte código (não se preocupe, explicaremos mais tarde):

Para executar nosso código, precisaremos compilar primeiro, tornando-o "pronto" para executar. Para compilar, nós usaremos um Compilador C chamado GCC. Abra o terminal e execute:

root@kali:~# gcc hello_shellter.c -o hello

Agora você pode executar seu código:

root@kali:~# ./hello


O resultado deve ser similar a imagem abaixo:

Conceitos Básicos

Agora vamos conhecer alguns conceitos sobre programação. Todos os exemplos que usaremos a partir de agora, são escritos com a linguagem de programação C.

Variáveis e Atribuições

As Variáveis representam um lugar que armazena valores, e estes "lugares" são uma região na memória. Você pode armazenar diferentes tipos de valores, como: texto, números inteiros, números de flutuação, estruturas de dados e muitos outros, dependendo da linguagem de programação que você está usando.

As linguagens de programação podem ser fortemente tipadas ou fracamente tipadas. Um idioma fortemente tipado significa que o programador deve definir o tipo de variável antes de usá-lo (se é um número inteiro ou um texto). Por outro lado, a linguagens fracamente tipadas não necessitam dessa especificação. Você terá uma melhor compreensão disso com a prática.

Como estamos usando C, uma linguagem fortemente tipada, nós temos que explicitamente declarar as variáveis e definir seu tipo.

Para atribuir um valor a uma variável, você usa o sinal ‘=’.

int a;

a = 10;

Comentários

Os comentários são muito importantes para a programação. Você os usa para explicar algumas linhas de código, para fazer anotações sobre métodos, ou explicitamente explicar coisas que você ainda deve fazer. Você verá a importância dos comentários quando precisar entender o código de outro codificador, ou mesmo quando você retornar ao seu próprio código depois de algum tempo.

Em C você pode escrever comentário com //. Tudo o que você escreve após estes caracteres na mesma linha, não será interpretado como código. Se você precisar de um comentário que tenha mais de uma linha, você pode usar /* Comentários */

Funções, Argumentos e Parâmetros

Durante a codificação, o seu programa pode se tornar grande facilmente, e você verá que há muitas instruções que você precisa executar muitas vezes em diferentes partes do seu código. É por isso que as funções existem. As funções são partes de código claramente separadas do resto do código, que você pode pedir ao seu programa para executá-las sempre que precisar. Com funções, você terá um pedaço de código que é reutilizado em seu programa, ou que você simplesmente precisa colocá-lo fora do caminho para deixar seu código mais organizado e claro.

Normalmente, você precisará trabalhar com variáveis dentro dos métodos, então você deve passar essas variáveis para a função como argumentos.
  • Parâmetros: Como você verá no trecho de código abaixo, as variáveis a e b são ambas os parâmetros. Essas são as variáveis que recebem os valores.
  • Argumentos: As variáveis value1 e value2 são ambas parâmetros. Essas são as variáveis que são enviadas para as funções.


Operações Aritiméticas

Você pode combinar variáveis com operadores matemáticos para obter novos valores. Na maioria das linguagens de programação, você pode usar todos os operadores básicos.


Condicionais

Às vezes você precisa fazer decisões no código em tempo de execução. Se um caso especial acontecer, o fluxo serguirá um determinado caminho, se o não ocorrer, seguirá um outro caminho.
Nós chamamos isso de condicionais. Os mais comuns são os IF e ELSE.

Digamos que gostarìamos de descobrir qual número é maior.

While Loops

Você usará While Loops quando precisar repetir o mesmo bloco de código repetidas vezes até alcançar uma determinada condição.

Vejamos um exemplo:


Suponha que input_from_user() é uma função que recebe uma entrada do usuário. Enquanto o usuário submeter como entrada algo diferente do número 1, o código continuará se repetindo.

For Loops

For Loops são semelhantes ao While Loops. Você usará quando precisar repetir um bloco de código até uma determinada condição acontecer. A principal diferente entre For e While é que usualmente você o primeiro quando sabe quantas vezes precisa executar o trecho de código, quando começa e quando termina. No segundo, você espera por um evento que pode inclusive nunca acontecer.

Por exemplo: Se você quer que seu código seja executado até o usuário digitar exit, a melhor opção para você é usar o While. Mas se você quer que o código seja executado apenas 100 vezes, você sabe exatamente quantas vezes o código se repetirá, então você utiliza o For.


O código acima está dizendo que, começando em k com o valor de 0, até k ter o valor 10, irá executar o código e em seguida incrementar o valor de k em 1. Isso significa que o código dentro do For irá se repetir 11 vezes.

Juntando Tudo

Bom trabalho! Agora você sabe algumas coisas sobre o básico de programação. Que tal colocar todos esses conceitos juntos em um desafio?

Nós construiremos um programa que resolve o desafio apresentado no começo da nossa lição.

Solving he Challenge

Some os números ímpares menores que 1000.

Como vimos no começo da lição, o algoritmo é muito simples.

O código abaixo resolve o problema. Vamos analisá-lo em detalhes.

Passo 1
Primeiro, declaramos as variáveis que precisaremos: sum, counter e rest (Linhas 5 a 7). Em seguida, inicializamos as variáveis com o valor de 0 para não corrermos o risco de um valor aleatório armazenado neste endereço de memória interferir no nosso código.

Passo 2
Agora vamos usar o For Loop. Queremos encontrar todos os números ímpares entre 0 e 1000. Então, vamos passar por todos eles para descobrir os ímpares e somá-los.

Passo 3
A linha 12 diz que estamos começando no contador igual a 0 e incrementando 1 até a variável count se tornar igual a 1000.

Com este For Loop, em cada iteração, o valor do contador aumentará. Na primeira iteração, o valor do contador será 1. Na segunda iteração, o valor será 2, e assim por diante, até 1000.

Passo 4
Agora, como descobrimos se um número é ímpar? Bem, isso é fácil. Nós dividimos o número em 2. Se o resto é 0, o número é igual. Se o resto for diferente de 0, o número é ímpar.

Para encontrar o resto da divisão, usamos o operador de mod %. Na linha 13, fazemos o cálculo do resto e armazenamos o resultado na variável.

Passo 5
Outra coisa que aprendemos foi o condicional if. Vamos usá-lo para verificar se o número em rest é maior do que 0. Se for o caso, isso significa que o número é ímpar e temos que somá-los. Nesse caso, somaremos o número ímpar com os outros em uma variável chamada 'sum' e armazenamos o novo valor na mesma variável.

Passo 6
Ótimo! Depois que o loop estiver concluído, ou seja, nós passarmos por todos os números de 0 a 1000, o valor armazenado em sum deve ter o resultado que queremos e precisamos apenas imprimi-lo.

Para imprimir o valor na variável, podemos usar a função de

print

. Nós escrevemos uma mensagem formatada e usamos %d para dizer que nesse ponto, imprimiremos um valor inteiro (Linha 19).

Passo 7
Na linha 21, retornamos 0 para finalizar o programa corretamente.

Bom trabalho! Tudo o que temos a fazer agora é compilar e executar o código da mesma forma que fizemos no pedido da lição.

Desafios

Apostamos que você pode pegar tudo o que aprendeu e implementar um código para resolver o seguinte desafio.

Referencias

[1] Introduction to algorithms 3trd edition.
[2] Programação Moderna em C.

Share: