Sheet 0

PABE Exercise Sheet 0

NOTE:

  • This sheet is not part of the mandatory sheets that are required for the admission for the final exam!
  • Contrary to the other sheets, you will not hand in solutions to the tasks on this sheet. Instead, you are advised to solve them on your own or in a group, and we will talk about the tasks in the first exercise session on 2020-11-13.
  • All tasks should be solved under Linux (Fedora, Arch Linux, Ubuntu, Kali, <your_favorite_distro_here>). Use a virtual machine if you do not have access to a native linux machine.

Task 1 - Python Programming With pwntools

Write a Python 3 script and use pwntools (link). In more detail, connect to pabe.seclab-bonn.de on port 11337 with remote (link) and do the following:

  • read the first string that always ends with an @ character (link)
  • read the second string that always ends with a % character
  • concatenate those two strings without the special characters @ and % and send them back to the server
  • the server will send a string back to tell you that everything was correct -> check that string!

Task 2 - Intel x86 Assembler

Have a look at the following snippet of assembler code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
xor eax, eax
xor ebx, ebx
xor ecx, ecx
mov ecx, 1
mov eax, 1337
mov ebx, 42
add eax, ebx
shl ecx, 2
add eax, ecx
push eax
push ebx
pop ecx
pop edx
lea eax, [ecx+eax]
lea ebx, [edx+ebx]

What are the final contents of eax, ebx, ecx, and edx? You can do this mentally (i.e. use your brain) or use a tool like Jasmin (link) or even Unicorn Engine if you want to get really fancy ;) (link)

Task 3 - Understanding a C Program

Look at the following source code:

 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
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#define MAX_BUFFER_SIZE 1024

int main(int argc, char **argv)
{
        char buffer[MAX_BUFFER_SIZE] = {0};
        char *user_input = NULL;

        user_input = (char *)malloc(MAX_BUFFER_SIZE);
    
        if (!user_input)
        {
                printf("error allocating memory\n");
                exit(1);
        }
    
        memset(user_input, 0, MAX_BUFFER_SIZE);
    
        printf("Enter a string:\n");
    
        if (!scanf("%1023s", user_input))
        {
                printf("error reading user intput\n");
                free(user_input);
                exit(1);
        }
    
        strncpy(buffer, user_input, MAX_BUFFER_SIZE);
    
        puts("Your input was:\n");
    
        puts(buffer);
    
        free(user_input);
    
        return 0;
}

Answer the following questions:

  1. What does the program do? Go through all the lines and try to understand (really understand) what it does.
  2. Where in memory (memory segment) does buffer reside?
  3. Where in memory (memory segment) do user_input and *user_input reside?
  4. What values does buffer contain after the initialization?
  5. What’s the difference between strcpy and strncpy? Is strncpy secure for all parameters?
  6. What’s the difference between user_input, &user_input, and *user_input?
  7. Look at the following assembler code:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    ...
    sub    esp, 0xc
    push   0x400
    call   8048430 <REDACTED@plt>
    add    esp, 0x10
    mov    DWORD PTR [ebp-0x410], eax
    cmp    DWORD PTR [ebp-0x410], 0x0
    jne    804862d <main+0x82>
    ...
    
    To which line(s) in the above source code might this snippet correspond? What is happening there?

Task 4 - Compilation of a C Program

Have a look at the following code in a file called main.c:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
  #include <stdio.h>
  
  int main(int argc, char **argv)
  {
  	if (argc != 2)
  	{
  		puts("I need one argument! Exiting...");
  		return 1;
  	}
  	
  	printf("Hello, %s!\n", argv[1]);
  	
  	return 0;
  }

Answer the following questions:

  1. What is the output of gcc -E -P main.c? What can you see? Where is the main() function and what are the other lines?
  2. Run gcc -S -masm=intel main.c and have a look at the newly created file main.s? Can you make sense of those lines? Is there a semantic connection between the C source code above? Can you find matching lines?
  3. Run gcc -c main.c and also run file main.o for the newly created file main.o. What does the output tell you?
  4. Run strings main.o, can you find anything related to the C source code?
  5. Run xxd main.o, what do you see? What do the different columns mean? Why are there sometimes . (dots) in the rightmost column?
  6. Run nm main.o, what do you see and more concrete what does U mean?

Have a look at the following code of a file called lib_hello.c:

1
2
3
4
5
6
7
8
  #include <stdio.h>
  
  void say_hello()
  {
  	puts("Hello, PABE student! Welcome to the lecture :)");
  
  	return;
  }

and this code called use_lib.c:

1
2
3
4
5
6
7
8
  extern void say_hello();
  
  int main()
  {
  	say_hello();
  
  	return 0;
  }

Answer the following questions:

  1. Compile the code with gcc -shared -fPIC lib_hello.c -o libhello.so and run file libhello.so. What is the output and how is it different to the output of file main.o?
  2. Run gcc -L$(pwd) -o use_lib use_lib.c -lhello and describe what the command does. What is the result? (if you want to run the final binary execute LD_LIBRARY_PATH=$(pwd) ./use_lib)
  3. In the previous gcc command… what happens if you leave the -L$(pwd) flag and why? (maybe ld -lhello --verbose will help you)

Task 5 - Bug Hunting

Download the following (not so well written) source code and try to win the game! The goal is to make the program print out the flag (#define FLAG "FLAG{REDACTED}"). Connect to pabe.seclab-bonn.de on port 11338 and get the flag! Hint: Maybe your name has an impact on the fortune…