commitc2b19dd5c3f0a781b4acdfef8726d96f5593a657parent37a7e3e567d4984a372e5a3135e28640e1000b51Author:therealFIGBERT <figbertwelner@gmail.com>Date:Sun, 5 Jan 2020 12:50:01 -0800 Add a walkthrough for the addition challengeDiffstat:

A | linux_and_misc/walkthroughs/addition.md | | | 72 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |

1 file changed, 72 insertions(+), 0 deletions(-)diff --git a/linux_and_misc/walkthroughs/addition.md b/linux_and_misc/walkthroughs/addition.md@@ -0,0 +1,72 @@ +# addition Walkthrough + +[addition](https://twinpeaks.cs.ucdavis.edu/challenge?id=9) is the first challenge where we interact with a server from our own machine with code. For this challenge I used the [pwntools library](https://github.com/Gallopsled/pwntools) for Python 3. + +Connecting to the server with `nc` spits out this response: +``` +John just noticed his homework is due in 10 seconds! +Help him finish his homework, which contains 50 additions. +Question 0 : 114314390 + 798790408 +Your answer: +``` +The pwntools' library `remote` object gives us several options for filtering out the input we receive, including the `recvline_contains` function. The `recvline_contains` function ["[receives] lines until one line is found which contains at least one of items"](https://docs.pwntools.com/en/stable/tubes.html?highlight=recvline_contains#pwnlib.tubes.tube.tube.recvline_contains). Combined with the `recv` function, we can filter out all of the unnecessary text from the server output with some pretty simple code: +```python +from pwn import * + +# Connecting to the server +connection = remote("twinpeaks.cs.ucdavis.edu", 30001) +# Receive the line with the equation +equation_line = connection.recvline_contains("Question") +``` +At this stage, we have a program that capture the question and then terminates. We now need to filter the variable. Based on the output from the `nc` connection, we can see that each question is formatted like this: `[QUESTION NUMBER] : [NUMBER ONE] + [NUMBER TWO]`. Now knowing the formatting, we can isolate the numbers and add them: +```python +# Split the equation into a list of question parts +# Value: ["QUESTION NUMBER", "NUMBER ONE + NUMBER TWO"] +equation_line_list = equation_line.split(b":") +# Select only the equation from the list, and eliminate whitespace +# Value: "NUMBER ONE + NUMBER TWO" +equation = equation_line_list[1].strip() +# Split equation bytestring into list of bytestring numbers +# Value: ["NUMBER ONE", "NUMBER TWO"] +numbers_bytestring_list = equation.split(b"+") +# Convert list of bytestring numbers to list of ints +# Value: [NUMBER_ONE, NUMBER_TWO] +numbers_list = [int(item.strip()) for item in numbers_bytestring_list] +# Find the sum of the numbers +number_sum = sum(numbers_list) +``` +We could now attempt to send the line, but if we look at the formatting we can see that one thing is missing - the server prompts us for our answer before it accepts input! Thus, we have to receive output before sending it back: +```python +# Receive the input prompt +connection.recv() +# Send the sum back as a bytestring +connection.sendline(bytes("%d"%num_sum, "utf-8") +``` +Now, we just have to stick all that in a loop that runs 50 times (and simplify it, if you'd like). The finalized code looks like this: +```python +# A CTF exploit by FIGBERT +# for UC Davis class ECS189M +# twinpeaks.cs.ucdavis.net:30001 +# Category: Linux and miscellaneous +# Challenge: addition +# 04/01/2020 +from pwn import * + +#Connecting to the server +connection = remote("twinpeaks.cs.ucdavis.edu", 30001) +for i in range(0,50): + #Recieving the equation + equation = connection.recvline_contains("Question") + #Splitting the equation into the two numbers to add + numbers = [int(item.strip()) for item in ((equation.split(b":")[1]).strip()).split(b"+")] + num_one = numbers[0] + num_two = numbers[1] + #Adding the two numbers + num_sum = sum(numbers) + print("Equation %d: %d + %d = %d"%(i+1, num_one, num_two, num_sum)) + connection.recv() + #Sending the password + connection.sendline(bytes("%d"%num_sum, "utf-8")) +connection.recv() +connection.interactive() +```