Blog

Posted by Oliver Siew­ers on No­vem­ber 26, 2020

Soft­ware En­gi­neer Chal­lenge

UP­DATE: We'll ac­cept so­lu­tions un­til Sun­day, Dec. 13th 2020.

Since we've had many promis­ing ap­pli­cants to our job of­fer, who we sadly can't in­vite all in per­son, we've de­cided to of­fer a tech­ni­cal chal­lenge. Please give brief an­swers and pro­vide them in Mark­down/​PDF for­mat to jobs@truf­flepig-foren­sics.com.

Part 1 (Re­verse en­gi­neer­ing)

Goal of the first chal­lenge is to find ways to get past the se­cu­rity mech­a­nisms. This chal­lenge has dif­fer­ent, valid so­lu­tions. We are not look­ing for the so­lu­tion it­self, but rather the way you ap­proach new prob­lems. We've tried to come up with a chal­lenge no ap­pli­cant is fa­mil­iar with. Please pro­vide a short de­scrip­tion of your thoughts on the chal­lenge and your so­lu­tions.

You will most likely need a tool like radare2 or ghidra to an­a­lyze the chal­lenge bi­nary, which is a Linux amd64 ap­pli­ca­tion.

Down­load chal­lenge

Part 2 (C++ / Al­go­rith­mic think­ing)

1. Short C++ Ques­tions

  • What does MyClass(MyClass &&c); mean in a class de­c­la­ra­tion?
  • What could be the rea­son to over­write the new op­er­a­tor?
  • When would you pass a pointer and when a ref­er­ence?

2. Data Ori­ented Ar­ray

Take a look at the fol­low­ing two code snip­pets and ex­plain which one you would pre­fer. Why?

char data[1024ull*1024][1024];

for (uint64_t i = 0, endi = 1024ull*1024; i < endi; ++i) {
    for (uint64_t j = 0, endj = 1024; j < endj; ++j) {
        work(data[i][j]);
    }
}
char data[1024ull*1024][1024];

for (uint64_t j = 0, endj = 1024; j < endj; ++j) {
    for (uint64_t i = 0, endi = 1024ull*1024; i < endi; ++i) {
        work(data[i][j]);
    }
}

EDIT: fixed out-of-bounds ac­cess

3. Al­go­rithm Recog­ni­tion

What does the fol­low­ing func­tion do? What are more de­scrip­tive names for unk1 and unk2?

bool mystery(const uint8_t *pData, size_t len, uint64_t unk1, uint64_t unk2, uint64_t *pOut) {
    for (uint64_t i = 0, end = len - sizeof(uint64_t); i <= end; ++i) {
        if ((*reinterpret_cast<const uint64_t *>(&pData[i]) ^ unk1) & unk2) {
            *pOut = i;
            return true;
        }
    }

    return false;
}

EDIT: full func­tion in­stead of al­go­rithm only

Part 3 (Mis­cel­la­neous)

  • What is your mo­ti­va­tion to work at Truf­flepig?
  • Please come up with a cre­ative strat­egy to mo­ti­vate your team
  • Name your fa­vorite quote