hey!. future me,(addressing myself) Status Update:So its been almost a year since i joined a company and having my career growing, but my personal goals are just at the same position when i left my student life. Gosh wish things where different, So another long time since i made my last post. time really flies by, so the most part im ok i guess with inner conflicts, mental forgetfullness, slow motion, slow thinking. For the past some weeks everything around me feels like it has been sped up, but i am still moving slowly.
Thing that got me interested - Google Capture the flag.
As i said, i haven’t given up all my hobbies, recently i was eager to participate in the capture the flag conducted by google, because i was free during that time cuz that was on a saturday and sunday, (not office hours,). So this post will cover that, i wont be writing everything, since this is ultimately for the sake of me that i am doing this.
challenges
Im going to be vague about most of the things, except the ones i felt where challenging and interesitng to me. so the first challenge was a binary challenge, that was pretty easy a 30 second view and string analysis of the file gave me the flag, “CTF{welcome_to_googlectf}” it was the beginning after all.
the next part was also a binay involved, but that binary was connecting to the internet to communicat, wireshark can be used for instance but using wireshark for this beginner task is an overkill, what i did was found out the server ip from the binary, connected to the server directly, got the flag, bypassing the protection from the binary,
the next part is a two parter, first you have to find the ip address of the server, then after connecting to the server, you have limited access, you do not have any permission what so ever, the flag is there in a file with no permission set to it, but you can access “bin/” directory with exec permissions to some of the executables, but no exec permissions to busybox binary, with some tweaking and wandering around this round is also simple.
the next round you are presented boot sector ntfs file. the file contains the details to the flag apparently, so we mount the ntfs file, find all the files that are likely to be the flag, apparently all the files are empty with 0 bytes,by filtering the files which are above 1kb, the results shows up as only one, we get a hint that the flag is stored in pic directory on the file’s extra attribute section.
the next level was an xss injection, that is pretty easy i guess, basically you have to get the admin’s cookies and session id to get the flag.
some of the challenges are very easy so I am not going to cover them, if you know basic reverse engineering and cyber security, you could solve them easily.
a challenge that was fresh and I have not seen anything like that challenge before, I am going to write about how I managed to solve that.
A challenge that was interesting to me.
so here comes the big thing that took me a lot of time to figure this out, It was a reversing challenge, it consisted of a python program with a file as argument to it, the argument file consist of emojis, python program emulates stack based vm with the smiles as instructions, Im gona walk through how i was able to solve this problem.
The source of the program was given, it was just a python program, but it was quite hard to understand what they where doing at first, the link to the files are below, check them out, you have to run them on python3.
the problem with this?.
So pretty much it prints a url, letter by letter, but gradually it slows down and at some point it stops, so the algorithm they are using might be the issue here, so when opening the program file you will find smiles inside of it, and the python program uses those smiles one by one as instrcutions and runs them. just like a modern cpu running the binary file. i was twisting my head around replacing smilies to understand the program, i could idenify pattersn but nothing more.
A little later I tried a different approach, which is print statements, the python progrm is still python right, so made some print statements in different places, then ran the program.
where I made the comments.
def xor(self):
a = self.stack.pop()
b = self.stack.pop()
print(" xor:: a:" + str(a) +" b:"+ str(b) +"\n")
self.stack.append(b ^ a)
def print_top(self):
print(self.stack);
sys.stdout.write(chr(self.stack.pop()))
sys.stdout.flush()
def push(self):
if self.rom[self.instruction_pointer] == '๐ฅ':
self.stack.append(self.accumulator1)
print("accumulator1 :" + str(self.accumulator1) )
elif self.rom[self.instruction_pointer] == '๐ฅ':
self.stack.append(self.accumulator2)
print("accumulator2 :" + str(self.accumulator1) )
else:
raise RuntimeError('Unknown instruction {} at position {}'.format(
self.rom[self.instruction_pointer], str(self.instruction_pointer)))
self.instruction_pointer += 1
def load(self):
num = 0
if self.rom[self.instruction_pointer] == '๐ฅ':
acc = 1
elif self.rom[self.instruction_pointer] == '๐ฅ':
acc = 2
else:
raise RuntimeError('Unknown instruction {} at position {}'.format(
self.rom[self.instruction_pointer], str(self.instruction_pointer)))
self.instruction_pointer += 1
while self.rom[self.instruction_pointer] != 'โ':
num = num * 10 + (ord(self.rom[self.instruction_pointer][0]) - ord('0'))
print("rom: "+str(ord(self.rom[self.instruction_pointer][0])) +" ord:"+ str((ord(self.rom[self.instruction_pointer][0]) - ord('0')) ))
self.instruction_pointer += 1
if acc == 1:
self.accumulator1 = num
else:
self.accumulator2 = num
self.instruction_pointer += 1
After making the comments things were much clearer to me, all the comments that I made in the above program I didn’t do it in one instance and run the program, I made some comments in the program run at and check the weather it make sense and added some more comments and then run it again and again… I have also attached the log files which was generated from the different runs.
outputWithXorWithAccumulator.txt
solving thought process
Download and check the different log files from above, analysing each of those health individually will give you an idea, well it give me an idea, all the different mechanics in the program were making sense to me now, the accumulator 1, accumulator 2, push instructions, pop instructions, load instructions…
You see when the program first runs, it just load the bunch of numbers into the memory after that it performs mathematical operations to find prime numbers, on the moment it finds a prime number it performs an XOR operation on a number that was initially loaded(a number that is in the top of the stack) this produces an integer value, this integer value corresponds to an ASCII character.. yeah! integer values are converted to ASCII character and then print out. This is the basis of the URL generator.
So we have the encoded URL as numbers in memory, you can easily find this out in the log files that I have attach, so we can easily extract those numbers, find the prime numbers ourselves and then perform xor operation and get the URL, easy right? .
So I cooked a a Python program that finds a series of prime numbers and then performs XOR operation. Running that I couldn’t find the URL it was printing random rubbish things. After inspecting closely I found out that the prime numbers or not in a series, are they were using some logic or or some other thing and only using certain prime numbers. This was the part where I was stuck and couldn’t get my brain around this. I was literally stuck for 45 minutes and clearly missed out the clue that was in front of me, maybe my office activities made my brain dull.
I found out that the prime numbers are in-fact in series, but the series contained only prime numbers that where palindromic. So I did some tweaks to my program and then executed it. Vola! I got the URL in an instant, with that URL I solved that challenge.
solution.
# Make sure to run the program in Python 3, I cooked up this program quickly so forgive my bad code,
import operator
toDecode = [17488, 16758, 16599, 16285, 16094, 15505, 15417, 14832, 14450, 13893, 13926, 13437, 12833, 12741, 12533, 11504, 11342, 10503, 10550, 10319, 975, 1007, 892, 893, 660, 743, 267, 344, 264, 339, 208, 216, 242, 172, 74, 49, 119, 113, 119,106]
def checkprime(num):
flag=True
for x in range(3,(int(num/2))+1):
if(num%x==0):
flag=False
return flag
def primeNumberGenerator():
primeNumberArr = [2,3,5,7]
for x in range(10,17488):
if(checkprime(x)):
primeNumberArr.append(x)
return primeNumberArr
def filterPalindromeFromPrime(primeNumberArr):
primePalindrome = []
for x in primeNumberArr:
if (str(x) == str(x)[::-1]):
primePalindrome.append(x)
return primePalindrome
def decode(PrimePalindromeArr):
toDecode.reverse()
url = []
print("toDecode Count:" +str(len(toDecode)))
print("PrimePalindromeArr Count:" +str(len(PrimePalindromeArr)))
for index, value in enumerate(toDecode):
character = operator.xor(PrimePalindromeArr[index],value)
print("palindromeValue:"+str(PrimePalindromeArr[index]))
print("value:"+str(value))
print("character:"+chr(character))
url.append(chr(character))
print("url:"+"".join(url))
if __name__ == '__main__':
primeArr = primeNumberGenerator()
PrimePalindromeArr = filterPalindromeFromPrime(primeArr)
decode(PrimePalindromeArr)
# Also forgot to mention there where three batches of toDecode, join them entirely to get the complete URL
I did manage to solve the challenges, but for the sake of this post I am gonna keep this short, already the post is very huge and it took me so long to write this. I know I am a bad typer(could not type very fast). I promise you that I will post all the challenges that were challenging to me. Bye See ya soon.