Solução da tarefa com pwnable.kr 07 - entrada. Entendendo pwntools

imagem

Neste artigo, analisaremos a solução de uma tarefa de vários níveis usando a biblioteca pwntools .

Informações Organizacionais
Especialmente para aqueles que desejam aprender algo novo e se desenvolver em qualquer uma das áreas de segurança da informação e da informática, escreverei e falarei sobre as seguintes categorias:

  • PWN;
  • criptografia (criptografia);
  • tecnologias de rede (rede);
  • reverso (engenharia reversa);
  • esteganografia (estegano);
  • pesquisa e exploração de vulnerabilidades na WEB.

Além disso, compartilharei minha experiência em análise forense de computadores, análise de malware e firmware, ataques a redes sem fio e redes locais, realização de protestos e explorações por escrito.

Para que você possa descobrir sobre novos artigos, software e outras informações, criei um canal no Telegram e um grupo para discutir quaisquer questões no campo da CID. Além disso, considerarei pessoalmente seus pedidos, perguntas, sugestões e recomendações pessoais e responderei a todos .

Todas as informações são fornecidas apenas para fins educacionais. O autor deste documento não se responsabiliza por nenhum dano causado a alguém como resultado do uso dos conhecimentos e métodos obtidos como resultado do estudo deste documento.

Solução de trabalho de entrada


Clicamos no ícone com a entrada de assinatura e somos informados de que precisamos nos conectar via SSH com a senha de convidado.

imagem

Quando conectado, vemos o banner correspondente.

imagem

Vamos descobrir quais arquivos estão no servidor e quais direitos temos.

ls -l 

imagem

Assim, podemos ler o código fonte do programa, pois existe o direito de ler para todos, e executar o programa de entrada com os direitos do proprietário (o bit fixo está definido). Vamos ver o resultado do código.

Código Fonte input.c
 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <arpa/inet.h> int main(int argc, char* argv[], char* envp[]){ printf("Welcome to pwnable.kr\n"); printf("Let's see if you know how to give input to program\n"); printf("Just give me correct inputs then you will get the flag :)\n"); // argv if(argc != 100) return 0; if(strcmp(argv['A'],"\x00")) return 0; if(strcmp(argv['B'],"\x20\x0a\x0d")) return 0; printf("Stage 1 clear!\n"); // stdio char buf[4]; read(0, buf, 4); if(memcmp(buf, "\x00\x0a\x00\xff", 4)) return 0; read(2, buf, 4); if(memcmp(buf, "\x00\x0a\x02\xff", 4)) return 0; printf("Stage 2 clear!\n"); // env if(strcmp("\xca\xfe\xba\xbe", getenv("\xde\xad\xbe\xef"))) return 0; printf("Stage 3 clear!\n"); // file FILE* fp = fopen("\x0a", "r"); if(!fp) return 0; if( fread(buf, 4, 1, fp)!=1 ) return 0; if( memcmp(buf, "\x00\x00\x00\x00", 4) ) return 0; fclose(fp); printf("Stage 4 clear!\n"); // network int sd, cd; struct sockaddr_in saddr, caddr; sd = socket(AF_INET, SOCK_STREAM, 0); if(sd == -1){ printf("socket error, tell admin\n"); return 0; } saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = INADDR_ANY; saddr.sin_port = htons( atoi(argv['C']) ); if(bind(sd, (struct sockaddr*)&saddr, sizeof(saddr)) < 0){ printf("bind error, use another port\n"); return 1; } listen(sd, 1); int c = sizeof(struct sockaddr_in); cd = accept(sd, (struct sockaddr *)&caddr, (socklen_t*)&c); if(cd < 0){ printf("accept error, tell admin\n"); return 0; } if( recv(cd, buf, 4, 0) != 4 ) return 0; if(memcmp(buf, "\xde\xad\xbe\xef", 4)) return 0; printf("Stage 5 clear!\n"); // here's your flag system("/bin/cat flag"); return 0; } 


A partir do código, conclui-se que precisamos passar por cinco níveis. Vamos levá-los por sua vez.

imagem

No primeiro nível, verifica-se que o número de argumentos do programa é 100. Nesse caso, o 65º elemento deve ser a cadeia “\ x00” e o 66º elemento deve ser “\ x20 \ x0a \ x0d”. Crie seu próprio diretório no diretório / tmp / e crie um script Python lá.

imagem

Para resolver o primeiro nível, criaremos uma matriz de cem linhas de 'A'. E atribua os argumentos necessários aos valores desejados. Podemos iniciar o processo com esses argumentos da seguinte maneira:

 from pwn import * a = ['A']*100 a[0] = '/home/input2/input' a[ord('A')] = '\x00' a[ord('B')] = '\x20\x0a\x0d' ex = process(argv=a) ex.interactive() 

imagem

Passamos o primeiro nível. Dê uma olhada no segundo.

imagem

Nesse nível, duas linhas são lidas, uma das entradas stdin padrão e a outra stderr. Precisamos criar dois arquivos que conterão essas linhas.

imagem

Abra fluxos para esses arquivos e especifique o descritor para o fluxo de um arquivo como o descritor stdin e outro arquivo como o descritor stderr.

 from pwn import * a = ['A']*100 a[0] = '/home/input2/input' a[ord('A')] = '\x00' a[ord('B')] = '\x20\x0a\x0d' fin = open('/tmp/ex/in.txt', 'r') ferr = open('/tmp/ex/err.txt', 'r') ex = process(argv=a, stdin=fin, stderr=ferr) fin.close() ferr.close() ex.interactive() 

imagem

Prosseguimos com a decisão do terceiro nível.

imagem

A função getenv () retorna o valor de uma variável de ambiente, que deve ser igual ao valor de referência. Portanto, você precisa criar uma variável de ambiente com um valor específico.

 from pwn import * a = ['A']*100 a[0] = '/home/input2/input' a[ord('A')] = '\x00' a[ord('B')] = '\x20\x0a\x0d' fin = open('/tmp/ex/in.txt', 'r') ferr = open('/tmp/ex/err.txt', 'r') e={'\xde\xad\xbe\xef':'\xca\xfe\xba\xbe'} ex = process(argv=a, stdin=fin, stderr=ferr, env=e) fin.close() ferr.close() ex.interactive() 

imagem

Nós gerenciamos a variável de ambiente, agora vamos começar do quarto nível.

imagem

De acordo com o código, podemos dizer que o programa abre um arquivo com o nome "\ x0a" e lê 4 caracteres, após o que os compara com os bytes "\ x00". Como os próprios caracteres e o nome do arquivo consistem em caracteres não imprimíveis, usamos python.

imagem

imagem

O último nível permanece. Vamos começar.

imagem

O programa abre o soquete na porta especificada no 66º argumento. Em seguida, ele recebe 4 bytes na rede e o compara com a string de referência. Precisamos adicionar outro argumento ao programa - o número da porta, estabelecer uma conexão e enviar os 4 bytes necessários.

 from pwn import * a = ['A']*100 a[0] = '/home/input2/input' a[ord('A')] = '\x00' a[ord('B')] = '\x20\x0a\x0d' a[ord('C')] = '1234' fin = open('/tmp/ex/in.txt', 'r') ferr = open('/tmp/ex/err.txt', 'r') e={'\xde\xad\xbe\xef':'\xca\xfe\xba\xbe'} ex = process(argv=a, stdin=fin, stderr=ferr, env=e) fin.close() ferr.close() ex.interactive() 

imagem

imagem

Isso é tudo, obtenha seus pontos.

imagem

Vejo você nos seguintes artigos!

Estamos em um canal de telegrama: um canal no telegrama .

Source: https://habr.com/ru/post/pt460249/


All Articles