Rating:

For a better view check our [githubpage](https://bsempir0x65.github.io/CTF_Writeups/Decompetition_CTF_2022/#baby_c) or [github](https://github.com/bsempir0x65/CTF_Writeups/tree/main/Decompetition_CTF_2022#baby_c) out
# Blaise

```assembly
; This is the disassembly you're trying to reproduce.
; It uses Intel syntax (mov dst, src).

main:
endbr64
push rbp
mov rbp, rsp
sub rsp, 0x40
mov [rbp-0x34], edi
mov [rbp-0x40], rsi
mov [rbp-0x30], 0
mov [rbp-0x28], -1
cmp [rbp-0x34], 3
jne block2
block1:
mov rax, [rbp-0x40]
add rax, 8
mov rax, [rax]
mov rdi, rax
call [email protected]
mov [rbp-0x30], rax
mov rax, [rbp-0x40]
add rax, 0x10
mov rax, [rax]
mov rdi, rax
call [email protected]
mov [rbp-0x28], rax
jmp block4
block2:
cmp [rbp-0x34], 2
jne block4
block3:
mov rax, [rbp-0x40]
add rax, 8
mov rax, [rax]
mov rdi, rax
call [email protected]
mov [rbp-0x28], rax
block4:
cmp [rbp-0x30], 0
js block7
block5:
cmp [rbp-0x28], 0
js block7
block6:
mov rax, [rbp-0x30]
cmp rax, [rbp-0x28]
jle block8
block7:
lea rsi, [mem1]; "USAGE: ./blaise (range)"
lea rdi, [_ZSt4cerr]
call [email protected]
mov rdx, rax
mov rax, [_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_]
mov rsi, rax
mov rdi, rdx
call [email protected]
mov edi, 1
call [email protected]
block8:
mov rax, [rbp-0x30]
mov [rbp-0x20], rax
block9:
mov rax, [rbp-0x20]
cmp rax, [rbp-0x28]
jg block14
block10:
mov [rbp-0x18], 1
mov rax, [rbp-0x20]
mov [rbp-0x10], rax
mov [rbp-8], 1
block11:
cmp [rbp-0x10], 0
je block13
block12:
mov rax, [rbp-0x18]
mov rsi, rax
lea rdi, [_ZSt4cout]
call [email protected]
mov esi, 9
mov rdi, rax
call [email protected]
mov rax, [rbp-0x18]
imul rax, [rbp-0x10]
mov [rbp-0x18], rax
mov rax, [rbp-0x18]
cqo
idiv [rbp-8]
mov [rbp-0x18], rax
sub [rbp-0x10], 1
add [rbp-8], 1
jmp block11
block13:
mov esi, 1
lea rdi, [_ZSt4cout]
call [email protected]
mov rdx, rax
mov rax, [_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_]
mov rsi, rax
mov rdi, rdx
call [email protected]
add [rbp-0x20], 1
jmp block9
block14:
mov eax, 0
leave
ret
```

Cause we have no clue about C++ either, we thougt why not. So we started with the same plan as before

- [ ] Figure out what the binary does
- [ ] Figure out what the different assemble statements would be in conjunction to the behaviour do
- [ ] Figure out how to programm in C++

So we got again our neat little decompiler graph as an example from [binary ninja](https://cloud.binary.ninja).

![ninja](https://raw.githubusercontent.com/bsempir0x65/CTF_Writeups/main/Decompetition_CTF_2022/img/blaise_binary.png)

As you can see we have multiple paths within the program. In the first part you can see that we have several checks for the input and an error message if the input is invalid. After that we could see that we had a while loop depending on the range you give as an input. Tough for us to see what happens in detail, but we were certain that we had again non malicous code. So we could jump into the dynamic analysis, by executing the binary.

```console
└─$ ./blaise 0 3
1
1 1
1 2 1
1 3 3 1
```
As an example valid output you can see that we have the mathematical/schematic tree where the branch below is the sum of the 2 above points in the graph. Google is your friend when you want to know more.

- [X] Figure out what the binary does

Yes we also figured out the error message. So once we had that we started again with the output of [ida](https://hex-rays.com/ida-free/) as our base code:

```cpp
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 v3; // rax
__int64 v4; // rax
__int64 v5; // rax
__int64 v7; // [rsp+10h] [rbp-30h]
__int64 v8; // [rsp+18h] [rbp-28h]
__int64 i; // [rsp+20h] [rbp-20h]
__int64 v10; // [rsp+28h] [rbp-18h]
__int64 v11; // [rsp+28h] [rbp-18h]
__int64 v12; // [rsp+30h] [rbp-10h]
__int64 v13; // [rsp+38h] [rbp-8h]

v7 = 0LL;
v8 = -1LL;
if ( argc == 3 )
{
v7 = atoll(argv[1]);
v8 = atoll(argv[2]);
}
else if ( argc == 2 )
{
v8 = atoll(argv[1]);
}
if ( v7 < 0 || v8 < 0 || v7 > v8 )
{
v3 = std::operator<<<std::char_traits<char>>(&std::cerr, "USAGE: ./blaise (range)");
std::ostream::operator<<(v3, &std::endl<char,std::char_traits<char>>);
exit(1);
}
for ( i = v7; i <= v8; ++i )
{
v10 = 1LL;
v12 = i;
v13 = 1LL;
while ( v12 )
{
v4 = std::ostream::operator<<(&std::cout, v10);
std::operator<<<std::char_traits<char>>(v4, 9LL);
v11 = v12 * v10;
envp = (const char **)(v11 % v13);
v10 = v11 / v13;
--v12;
++v13;
}
v5 = std::ostream::operator<<(&std::cout, 1LL, envp);
std::ostream::operator<<(v5, &std::endl<char,std::char_traits<char>>);
}
return 0;
}
```

This one was not even runable so we go over it one by one to figure out how to get this running. After multiple times googling everything for that language from *hello world* until specific functions was everything there. P.S: This time we were also certain that importing stuff is intended. So we ended up with this:

```cpp
/*
// B
// L A
// I S E
*/ //intmain
#include <stdlib.h> // use atoll
#include <string> // if you want to have fun with strings
#include <iostream> // seems to be necessary if you want to write something on the console and
#include <system_error> // when you want to use error messages

int main(int argc, const char **argv, const char **envp) //no clue about the inputs its from ida
{
// we kicked out int64 seems that ida decompiler in the cloud uses 64bit systems. Not necessary in this case plus some unused variables left us too after the clean up

int v7; // [rsp+10h] [rbp-30h]
int v8; // [rsp+18h] [rbp-28h]
int i; // [rsp+20h] [rbp-20h]
int v10; // [rsp+28h] [rbp-18h]
int v11; // [rsp+28h] [rbp-18h]
int v12; // [rsp+30h] [rbp-10h]
int v13; // [rsp+38h] [rbp-8h]

v7 = 0; // whatever the LL long long int is used here we just used ints so a 0 was enough
v8 = -1;
if ( argc == 3 ) // the check if you have 2 or less arguements all others gets ignored
{
v7 = atoll(argv[1]); // atoll makes actuall integer of our input which is parsed as strings
v8 = atoll(argv[2]);
}
else if ( argc == 2 )
{
v8 = atoll(argv[1]);
}
if ( v7 < 0 || v8 < 0 || v7 > v8 ) // this check is checking if the first value is smaller then the second and equal or above 0 to ensure that we gave a positiv range
{
std::cerr<< "USAGE: ./blaise (range)"; // we learned that stf::something is the print error message definition of c++
// also we got rid of the complex streaming function calls from ida. This happens cause most of the stuff is done by the compiler for us
exit(1);
}
for ( i = v7; i <= v8; ++i )
{
v10 = 1;
v12 = i;
v13 = 1;
while ( v12 != 0 )
{
std::cout<< v10 << "\t" << std::flush; // took a while but we figured out that the spaces in between are tabs so \t for tabs
v11 = v12 * v10; // magic for the leafs in the branches of the tree continued over 4 lines. Check google to find the formular
v10 = v11 / v13;
v12--;
v13++;
}
std::cout<< 1 << std::endl;
}
return 0;
}
```
So we had a running code and our internal tests showed that in small the program we had is working. But we never looked into the disassembly per se. If you never had done something in c++ before its kinda hard to figure the easy stuff like print something ... . So once we had that 3 test cases out of 5 went successful trough for us and in total we had 38% in this challenge. This was more than enough for a crash course in c++ . Unfourtnatly this time we did not really do reverse engineering it was more try and error like a programming exercise, with the difference that we started with a broken code. So like any tutor at unverisity once they have you to teach something and explain why your code is broken. (? ͡❛ ͜ʖ ͡❛)? love you all my tutors (? ͡❛ ͜ʖ ͡❛)?

![result](https://raw.githubusercontent.com/bsempir0x65/CTF_Writeups/main/Decompetition_CTF_2022/img/blaise_result.png)

Maybe we come once back for it but for now we had enough fun. You can continue from here or check other write ups.

Original writeup (https://bsempir0x65.github.io/CTF_Writeups/Decompetition_CTF_2022/#blaise).