Skip to content

Commit 005d4ff

Browse files
committed
Adding an old guest challenge made for Winja CTF
1 parent a1c417c commit 005d4ff

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+2723
-0
lines changed

other/re-risky/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
### RiskY
2+
This was a guest challenge made for the Winja 2018 CTF.
3+
4+
It comes in two flavors:
5+
6+
1. `directors-cut` - the initial version of the challenge - a rather hard and lengthy task.
7+
2. `split-version` - 4 easy challenges derived from the initial version.
8+
9+
Enjoy!
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
RiskY was created by Gynvael Coldwind / Google Inc.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
flag{APrettyRiskvTask}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
This file contains the description of how the challenge is constructed and hints
2+
on how it should be solved.
3+
4+
1. What is this task about?
5+
The "RiskY" re450 is a multi-layer reverse-engineering challenge. While no layer
6+
is obfuscated in itself, the transitions between layers itself is the source of
7+
difficulty of the task.
8+
9+
There are 4 layers:
10+
- Initial .pyc file
11+
- In-memory loaded .pyc module
12+
- In-memory loaded x86_64 ELF binary (trivial RISC-V emulator)
13+
- In-memory loaded RISC-V flat binary (flag checker)
14+
15+
Given that the flag checker is in the last layer, it is expected for the player
16+
to either reverse all the layers in order to understand how the flag checker
17+
works, or find a side channel attack.
18+
19+
The flag checker itself is a simple bit mixer, that shuffles a 256-bit set and
20+
NOTs a selected subset, and then compares to the hardcoded string.
21+
Given the construction of the checker it is only possible to have 1 solution for
22+
this task.
23+
24+
2. Hints for solving:
25+
First layer can be decompiled with any available Python decompiler.
26+
27+
The second layer can be stored into a .pyc file (this requires adding a proper
28+
magic and timestamp) and decompiled the same way as the first layer.
29+
30+
The third layer is the x86_64 ELF binary, which can be dumped and analyzed. It
31+
doesn't make ANY syscalls and doesn't have ANY imports. It's up to the player
32+
to either reverse-engineer it to realize it's a VM, or figure out that it's
33+
the RISC-V architecture (organizers should not hint about it being a RISK-V).
34+
35+
The forth layer (RISC-V flat binary) will take some reverse-engineering as there
36+
are no decompilers for RISC-V (as far as I know at least). However the code is
37+
pretty short so it shouldn't take too much time.
38+
39+
The last step is to either reverse the bit mixer, or brute-force it bit-by-bit.
40+
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright 2018 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
//
15+
// To be compiled to RISC-V.
16+
#include <stdbool.h>
17+
#include <stdint.h>
18+
19+
#include "mixer.c"
20+
21+
bool checker(const uint8_t *f) {
22+
uint8_t output[32] = {0};
23+
24+
for (unsigned i = 0U; i < 256U; i++) {
25+
unsigned bit = mix_bits[i] & 7U;
26+
unsigned byte = mix_bits[i] >> 3U;
27+
uint8_t b = (f[byte] >> bit) & 1U;
28+
b ^= mix_flips[i];
29+
bit = i & 7U;
30+
byte = i >> 3U;
31+
output[byte] |= b << bit;
32+
}
33+
34+
unsigned int sum = 0;
35+
for (unsigned i = 0; i < 32; i++) {
36+
sum += output[i] ^ flag[i];
37+
}
38+
39+
return sum == 0;
40+
}
41+
Binary file not shown.
Binary file not shown.
Binary file not shown.

other/re-risky/directors-cut/spoilers_and_source/src/checker_as_mem.c

Lines changed: 14 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/python
2+
# Copyright 2018 Google LLC
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# https://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
d = bytearray(open("checker.flat", "rb").read())
16+
o = ','.join(["0x%.2x" % x for x in d])
17+
18+
f = open("checker_as_mem.c", "w");
19+
f.write("uint8_t mem[] = {")
20+
f.write(o)
21+
f.write("};\n")

0 commit comments

Comments
 (0)