Skip to content

Reading a File

Reading a File

Reading a File

Do you feel ready to write some useful code? We hope so! You're mostly on your own this time! Don't forget that you can reference your solutions from other levels!

For this exercise, we're going to read a specific file… let's say, /var/northpolesecrets.txt… and write it to stdout. No reason for the name, but since this is Jack Frost's troll-trainer, it might be related to a top-secret mission!

Solving this is going to require three syscalls! Four if you decide to use sys_exit - you're welcome to return or exit, just don't forget to fix the stack if you return!

First up, just like last exercise, call sys_open. This time, be sure to open /var/northpolesecrets.txt.

Second, find the sys_read entry on the syscall table, and set up the call. Some tips:

  1. The file descriptor is returned by sys_open
  2. The buffer for reading the file can be any writeable memory - rsp is a great option, temporary storage is what the stack is meant for
  3. You can experiment to find the right count, but if it's a bit too high, that's perfectly fine

Third, find the sys_write entry, and use it to write to stdout. Some tips on that:

  1. The file descriptor for stdout is always 1
  2. The best value for count is the return value from sys_read, but you can experiment with that as well (if it's too long, you might get some garbage after; that's okay!)

Finally, if you use rsp as a buffer, you won't be able to ret - you're going to overwrite the return address and ret will crash. That's okay! You remember how to sys_exit, right? :)

(For an extra challenge, you can also subtract from rsp, use it, then add to rsp to protect the return address. That's how typical applications do it.)

Good luck!

Hints

  • This is the last challenge. Good luck!

To complete this challenge we need to use sys_open, sys_read, and sys_write, and just for good measure, I will end on a sys_exit. For my own edification, I've written the requirements to use each of these functions below:

sys_open

To use sys_open:

  • Set rax to 2 to set up the syscall.
  • Set rdi to the address of the filename
  • Set rsi to 0
  • Set rdx to 0

The descriptor is then stored in rax!

sys_read

To use sys_read:

  • Set rax to 0 to set up the syscall.
  • Set rdi to the file descriptor we are reading
  • Set rsi to the buffer we want to store the data to, in this case rsp (put it into the stack!)
  • Set rdx to the size we are reading

sys_write

To use sys_write:

  • Set rax to 1.
  • Set rdi to the file descriptor we are writing to
  • Set rsi to the location of the text we are writing
  • Set rdx to the length of the string we are writing

sys_exit

To use sys_exit:

  • Set rax to 60.
  • Set rdi to whatever error code you want to exit with (1225)

With the above in mind, I've written the following

 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
; TODO: Get a reference to this
call yuletide_cheer
db '/var/northpolesecrets.txt',0

yuletide_cheer:
pop rdi

; TODO: Call sys_open
mov rax, 2
mov rsi, 0
mov rdx, 0
syscall

; store the FD in r8 because why not
mov r8, rax

; TODO: Call sys_read on the file handle and read it into rsp
mov rax, 0
mov rdi, r8
mov rsi, rsp
mov rdx, 200
syscall

; count is in rax, move it to r9, because I dunno, get outta here kid ya bother me
mov r9, rax

; TODO: Call sys_write to write the contents from rsp to stdout (1)
mov rax, 1
mov rdi, 1
mov rsi, rsp
mov rdx, r9
syscall

; TODO: Call sys_exit
mov rax, 60
mov rdi, 1225
syscall

The resulting text of the above function:

Secret to KringleCon success: all of our speakers and organizers, providing the gift of cyber security knowledge, free to the community.

After completing the above, I was told that I can add ?cheat after the URL (before the #) to unlock the solutions! But what's the fun in that?