Join the discord

HackThisSite.org - Application challenges

19 Nov, 2017 14:13
This is something I was planning for a long time.
THIS ARTICLE IS A GIANT SPOILER!
If you haven't completed the achievements already but plan to do it some day, you should stop reading it.

There - you've been warned.

I solved these challenges long ago. In matter of fact I solved them so long ago, I totally forgot some of them and basically did them as it was my first time.
One thing I should mention is that really tried to stay on point without falling into too much details. Still, some of the challenges got a bit chunky but oh well, you know me.

For all of the challenges I've used the following approach:

- PE forensic to determine the compiler/linker and pick the right tool for further analysis
- Look for the "Invalid password" message
- Look around the imported functions for StringCompare, strcmp, memcmp, etc.
- Real time debugging

To accomplish this task, I've used the following tools:

- PEiD v0.95 - Discontinued development, but still do the job done
- Detect it Easy v1.01 - Or simply DiE is the natural successor of PEiD
- TrID v2.24 - File Identifier
- x86dbg v25 - the better ollydbg
- HxD v1.7.7.0 - my choice of a HEX editor
- IDA v6.6 - Interactive disassembler
- VBReFormer v5.0 - it's what I got
- whatever I forgot to mention







Application Challenge #1 (Windows)


Target: app1win.exe
Requirement: Find the password
Difficulty: easy

Here's what I have here:


According to DiE, the application is linked with "Microsoft Linker(3.0)[EXE32]", but no compiler is detected:


PEiD wasn't helpful at all:


However, TrID nailed it:


I intentionally wrote an article about reverse engineering REALbasic applications some time ago.
Now I can use the IDAPython script to rebuild it and analyse it further in IDA. You can refer to the article if something is unclear.

Moving on.
After loading app1win.exe in IDA, running the rebuilder script, and using IDA's decompiler, I'm here:
OVERLAY entry point, IDA decompileint main_overlay() {
    RuntimeInit();
    sub_570C9C();
    RuntimeRegisterFileType(&prm_0002, &prm_0001, &prm_0000, 0);
    sub_57083F();
    sub_570B19();
    RuntimeRun();
    var_0001 = 0;
    RuntimeUnlockObject(0);
    RuntimeExit();
    return 0;
}

Now, the named functions like RuntimeInit(), RuntimeRegisterFileType(), etc. are part of REALbasic's Framework API, so I'll use them as milestones, without tracing inside them.
The parameters you see around, starting with "prm_" is user defined data, and I'll watch them closer. Also, the procedures starting with "sub_" are part of the user code, so I'll trace these too.

So, let's see what we have here.
Starting with RuntimeInit(), then RuntimeRegisterFileType(), some unknown procedures, RuntimeRun() and RuntimeExit() in the end.
Logically I should be interested in everything before RuntimeRun() and in the current case this is sub_570B19():
OVERLAY_EP->>sub_570B19(), IDA decompileint sub_570B19() {
    // trimmed

    RuntimeStackCheck();
    RuntimeUnlockObject(0);
    v2 = sub_56C5E7();
    if ( !v2 )
        RuntimeNilObject();
    WindowForceUpdateFrontBuffer(v2);
    RuntimeUnlockObject(v2);
    return 0;
}

Here, we have RuntimeUnlockObject(), some unknown procedure sub_56C5E7() and WindowForceUpdateFrontBuffer(), so we go inside sub_56C5E7():
OVERLAY_EP->sub_570B19()->sub_56C5E7(), IDA decompileint sub_56C5E7() {
    // trimmed

    RuntimeStackCheck();
    RuntimeUnlockObject(0);
    RuntimeLockUnlockObjects(0, 0);
    RuntimeUnlockObject(0);
    v0 = sub_562716(&prm_0139);
    v6 = RuntimeNewObject(v0);
    WindowDefaultConstructor(v6);
    RuntimeLockUnlockObjects(v6, 0);
    RuntimeUnlockObject(0);
    v1 = sub_562716(v4);
    v5 = RuntimeCheckCast(v6, v1);
    RuntimeLockObject(v5);
    RuntimeUnlockObject(v6);
    RuntimeUnlockObject(0);
    RuntimeUnlockObject(v6);
    RuntimeUnlockObject(v5);
    return v5;
}

Again, lost of framework calls, and a unknown call sub_562716(), taking prm_0139 as parameter.
Checking what prm_0139 holds shows I'm on the right track:
prm_0139, IDA disassemblyOVERLAY:00571541 prm_0139        struc_PRM <1, offset str_0139, 9, 7, 8000100h>
OVERLAY:00571555 str_0139        db 7,'Window1',0,0,0,0

This is obviously the window constructor procedure, so I'm going in:
OVERLAY_EP->sub_570B19()->sub_56C5E7()->sub_562716(), IDA decompileint sub_562716() {
// trimmed

    RuntimeStackCheck();
    if (!var_0032) {
        v0 = RuntimeLookupClass(&prm_0079);
        var_0032 = RuntimeNewClass(v0, 14, 0, 21);
        *(_DWORD *)(var_0032 + 4) = &prm_0139;
        RuntimeLockString(&prm_0139);
        v1 = var_0032;
        *(_DWORD *)(var_0032 + 16) = 0;
        *(_DWORD *)(v1 + 12) = 140;
        *(_DWORD *)(v1 + 20) = &unk_5626D8;
        *(_DWORD *)(v1 + 24) = &unk_5626F7;
        v2 = *(_DWORD *)(v1 + 32);
        *(_DWORD *)v2 = &unk_562CE7;
        *(_DWORD *)(v2 + 4) = &prm_0081;
        RuntimeLockString(&prm_0081);
        *(_DWORD *)(v2 + 8) = aUlBL;
        *(_DWORD *)(v2 + 12) = &prm_0082;
        RuntimeLockString(&prm_0082);
        *(_DWORD *)(v2 + 16) = &unk_563AFF;
        *(_DWORD *)(v2 + 20) = &prm_0083;
        RuntimeLockString(&prm_0083);
        *(_DWORD *)(v2 + 24) = &unk_563DD6;
        *(_DWORD *)(v2 + 28) = &prm_0084;
        RuntimeLockString(&prm_0084);
        *(_DWORD *)(v2 + 32) = &unk_5640AD;
        *(_DWORD *)(v2 + 36) = &prm_0085;
        RuntimeLockString(&prm_0085);
        *(_DWORD *)(v2 + 40) = &unk_564384;
        *(_DWORD *)(v2 + 44) = &prm_0086;
        RuntimeLockString(&prm_0086);
        *(_DWORD *)(v2 + 48) = &unk_56465B;
        *(_DWORD *)(v2 + 52) = &prm_0087;
        RuntimeLockString(&prm_0087);
        *(_DWORD *)(v2 + 56) = &unk_56AD50;
        *(_DWORD *)(v2 + 60) = &prm_0088;
        RuntimeLockString(&prm_0088);
        *(_DWORD *)(v2 + 64) = &unk_56B027;
        *(_DWORD *)(v2 + 68) = &prm_0089;
        RuntimeLockString(&prm_0089);
        *(_DWORD *)(v2 + 72) = &unk_56B3C7;
        *(_DWORD *)(v2 + 76) = &prm_0090;
        RuntimeLockString(&prm_0090);
        *(_DWORD *)(v2 + 80) = &unk_56B767;
        *(_DWORD *)(v2 + 84) = &prm_0091;
        RuntimeLockString(&prm_0091);
        *(_DWORD *)(v2 + 88) = &unk_56BB07;
        *(_DWORD *)(v2 + 92) = &prm_0092;
        RuntimeLockString(&prm_0092);
        *(_DWORD *)(v2 + 96) = &unk_56BEA7;
        *(_DWORD *)(v2 + 100) = &prm_0093;
        RuntimeLockString(&prm_0093);
        *(_DWORD *)(v2 + 104) = &unk_56C247;
        *(_DWORD *)(v2 + 108) = &prm_0094;
        RuntimeLockString(&prm_0094);
        v3 = *(_DWORD *)(var_0032 + 40);
        *(_DWORD *)v3 = &unk_562CE7;
        *(_DWORD *)(v3 + 4) = &prm_0095;
        RuntimeLockString(&prm_0095);
        *(_DWORD *)(v3 + 8) = aUlBL;
        *(_DWORD *)(v3 + 12) = &prm_0096;
        RuntimeLockString(&prm_0096);
    }
    return var_0032;
}
This looks promising.

Because it's the Window constructor procedure, I expect to find things like creating window controls, static texts, menus, buttons, button actions and so on.
Since the application consists of a text field and a button, i'm interested in anything related to grabbing data from a text field and button actions.
Also, note that these variables starting with "unk_" are procedures that weren't resolved automatically by IDA, so I'll basically have to go to the said address and press 'C' to convert it into code.

The logic in the above code is pretty simple.
Basically first we crate a Class using RuntimeNewClass(), then assign procedures and parameters to it like this:
Procedures assignment, IDA decompile*(_DWORD *)v2 = &unk_562CE7;           // Procedure 1
*(_DWORD *)(v2 + 4) = &prm_0081;       // Procedure 1 parameter
RuntimeLockString(&prm_0081);
*(_DWORD *)(v2 + 8) = aUlBL;           // Procedure 2
*(_DWORD *)(v2 + 12) = &prm_0082;      // Procedure 1 parameter
RuntimeLockString(&prm_0082);
*(_DWORD *)(v2 + 16) = &unk_563AFF;    // Procedure 3
*(_DWORD *)(v2 + 20) = &prm_0083;      // Procedure 3 parameter
RuntimeLockString(&prm_0083);

Now i can take a look at every "prm_" and take a look at the interesting ones.
The complete list of parameters here is this:
Rarameters list, IDA disassemblyOVERLAY:00571525 prm_0079        struc_PRM <1, offset str_0079, 8, 6, 600h>
OVERLAY:00571539 str_0079        db 6,'Window',0
OVERLAY:00571541 prm_0139        struc_PRM <1, offset str_0139, 9, 7, 8000100h>
OVERLAY:00571555 str_0139        db 7,'Window1',0,0,0,0
OVERLAY:00571561 prm_0081        struc_PRM <1, offset str_0081, 15h, 13h, 8000100h>
OVERLAY:00571575 str_0081        db 19,'#Layout%%o<Window1>',0,0,0,0
OVERLAY:0057158D prm_0082        struc_PRM <1, offset str_0082, 1Dh, 1Bh, 8000100h>
OVERLAY:005715A1 str_0082        db 27,'#CreateControls%%o<Window1>',0,0,0,0
OVERLAY:005715C1 prm_0083        struc_PRM <1, offset str_0083, 26h, 24h, 8000100h>
OVERLAY:005715D5 str_0083        db 36,'StaticText1%o<StaticText>%o<Window1>',0,0,0
OVERLAY:005715FD prm_0084        struc_PRM <1, offset str_0084, 1Dh, 1Bh, 8000100h>             // / create the EDIT field
OVERLAY:00571611 str_0084        db 27,'key%o<EditField>%o<Window1>',0,0,0,0                    // \
OVERLAY:00571631 prm_0085        struc_PRM <1, offset str_0085, 26h, 24h, 8000100h>
OVERLAY:00571645 str_0085        db 36,'StaticText2%o<StaticText>%o<Window1>',0,0,0
OVERLAY:0057166D prm_0086        struc_PRM <1, offset str_0086, 26h, 24h, 8000100h>             // / create the BUTTON
OVERLAY:00571681 str_0086        db 36,'PushButton1%o<PushButton>%o<Window1>',0,0,0             // \
OVERLAY:005716A9 prm_0087        struc_PRM <1, offset str_0087, 2Dh, 2Bh, 8000100h>             // / assign action to the BUTTON
OVERLAY:005716BD str_0087        db 43,'PushButton1_Action%%o<Window1>o<PushButton>',0,0,0,0    // \
OVERLAY:005716ED prm_0088        struc_PRM <1, offset str_0088, 26h, 24h, 8000100h>
OVERLAY:00571701 str_0088        db 36,'StaticText3%o<StaticText>%o<Window1>',0,0,0
OVERLAY:00571729 prm_0089        struc_PRM <1, offset str_0089, 21h, 1Fh, 8000100h>
OVERLAY:0057173D str_0089        db 31,'EditUndo%o<MenuItem>%o<Window1>',0,0,0,0
OVERLAY:00571761 prm_0090        struc_PRM <1, offset str_0090, 20h, 1Eh, 8000100h>
OVERLAY:00571775 str_0090        db 30,'EditCut%o<MenuItem>%o<Window1>',0
OVERLAY:00571795 prm_0091        struc_PRM <1, offset str_0091, 21h, 1Fh, 8000100h>
OVERLAY:005717A9 str_0091        db 31,'EditCopy%o<MenuItem>%o<Window1>',0,0,0,0
OVERLAY:005717CD prm_0092        struc_PRM <1, offset str_0092, 22h, 20h, 8000100h>
OVERLAY:005717E1 str_0092        db 32,'EditPaste%o<MenuItem>%o<Window1>',0,0,0
OVERLAY:00571805 prm_0093        struc_PRM <1, offset str_0093, 22h, 20h, 8000100h>
OVERLAY:00571819 str_0093        db 32,'EditClear%o<MenuItem>%o<Window1>',0,0,0
OVERLAY:0057183D prm_0094        struc_PRM <1, offset str_0094, 25h, 23h, 8000100h>
OVERLAY:00571851 str_0094        db 35,'FileQuit%o<QuitMenuItem>%o<Window1>',0,0,0,0
OVERLAY:00571879 prm_0095        struc_PRM <1, offset str_0095, 8, 6, 8000100h>
OVERLAY:0057188D str_0095        db 6,'Layout',0
OVERLAY:00571895 prm_0096        struc_PRM <1, offset str_0096, 10h, 0Eh, 8000100h>
OVERLAY:005718A9 str_0096        db 14,'CreateControls',0

So, I'm interested in prm_0087 associated procedure:
sub_56465B(prm_0087), IDA decompileint __cdecl sub_56465B(int a1, int a2) {
// trimmed

    RuntimeLockObject(a1);
    RuntimeLockObject(a2);
    RuntimeStackCheck();
    RuntimeUnlockString(0);
    RuntimeUnlockObject(0);
    v167 = (*(int (__cdecl **)(int))(*(_DWORD *)(a1 + 4) + 24))(a1);
    if ( !v167 )
        RuntimeNilObject();
    v166 = editTextGetter(v167);                                          // Get the user entered code
    RuntimeLockUnlockStrings(v166, 0);
    if ( RuntimeStringCompare(v166, &prm_0106) ) {                        // Compare the user code with whatever prm_0106 holds
        if ( RuntimeStringCompare(v166, &prm_0109) ) {                    // Compare the user code with whatever prm_0109 holds
            if ( RuntimeStringCompare(v166, &prm_0112) ) {                // Compare the user code with whatever prm_0112 holds
                if ( RuntimeStringCompare(v166, &prm_0115) ) {            // Compare the user code with whatever prm_0115 holds
                    if ( RuntimeStringCompare(v166, &prm_0118) ) {        // Compare the user code with whatever prm_0118 holds
                        if ( RuntimeStringCompare(v166, &prm_0121) ) {    // Compare the user code with whatever prm_0121 holds
                            RuntimeMsgBox(&prm_0124);                     // Throw message from prm_0124
                        } else {

// trimmed

Those RuntimeStringCompare() calls look interesting, so let's see their params:
List of RuntimeStringCompare parameters, IDA disassemblyOVERLAY:005718E9 prm_0106        struc_PRM <1, offset str_0106, 15h, 13h, 8000100h>
OVERLAY:005718FD str_0106        db 19,'0130-1414-5624-1341',0,0,0,0
;...
OVERLAY:00571975 prm_0109        struc_PRM <1, offset str_0109, 15h, 13h, 8000100h>
OVERLAY:00571989 str_0109        db 19,'3810-1941-5861-5351',0,0,0,0
;...
OVERLAY:005719A1 prm_0112        struc_PRM <1, offset str_0112, 15h, 13h, 8000100h>
OVERLAY:005719B5 str_0112        db 19,'8361-9811-5511-8134',0,0,0,0
;...
OVERLAY:005719CD prm_0115        struc_PRM <1, offset str_0115, 15h, 13h, 8000100h>
OVERLAY:005719E1 str_0115        db 19,'9484-2341-5696-5321',0,0,0,0
;...
OVERLAY:005719F9 prm_0118        struc_PRM <1, offset str_0118, 15h, 13h, 8000100h>
OVERLAY:00571A0D str_0118        db 19,'0138-4411-5902-2411',0,0,0,0
;...
OVERLAY:00571A25 prm_0121        struc_PRM <1, offset str_0121, 15h, 13h, 8000100h>
OVERLAY:00571A39 str_0121        db 19,'7692-3349-1914-4567',0,0,0,0

Trying any of these gives me this result:


Nice. I've got what I need, but let's see where that "smashthestate" came from.

The prm_0124 holds the "Sorry, you entered an incorrect serial number. Please re-enter", so that's the bad password message.
In the else statement the code goes like this:
Site code generation, IDA decompile// trimmed multiple calls to RuntimeUnlockString(0);
v30 = StringDBCSChr(115);                 // 's'
v29 = RuntimeAddString(&prm_0122, v30);   // "Contratulations! The password to this level is \'" (the typo is not mine)
RuntimeUnlockString(0);
v28 = StringDBCSChr(109);                 // 'm'
v27 = RuntimeAddString(v29, v28);
RuntimeUnlockString(0);
v26 = StringDBCSChr(97);                  // 'a'
v25 = RuntimeAddString(v27, v26);
RuntimeUnlockString(0);
v24 = StringDBCSChr(115);                 // 's'
v23 = RuntimeAddString(v25, v24);
RuntimeUnlockString(0);
v22 = StringDBCSChr(104);                 // 'h'
v21 = RuntimeAddString(v23, v22);
RuntimeUnlockString(0);
v20 = StringDBCSChr(116);                 // 't'
v19 = RuntimeAddString(v21, v20);
RuntimeUnlockString(0);
v18 = StringDBCSChr(104);                 // 'h'
v17 = RuntimeAddString(v19, v18);
RuntimeUnlockString(0);
v16 = StringDBCSChr(101);                 // 'e'
v15 = RuntimeAddString(v17, v16);
RuntimeUnlockString(0);
v14 = StringDBCSChr(115);                 // 's'
v13 = RuntimeAddString(v15, v14);
RuntimeUnlockString(0);
v12 = StringDBCSChr(116);                 // 't'
v11 = RuntimeAddString(v13, v12);
RuntimeUnlockString(0);
v10 = StringDBCSChr(97);                  // 'a'
v9 = RuntimeAddString(v11, v10);
RuntimeUnlockString(0);
v8 = StringDBCSChr(116);                  // 't'
v7 = RuntimeAddString(v9, v8);
RuntimeUnlockString(0);
v6 = StringDBCSChr(101);                  // 'e'
v5 = RuntimeAddString(v7, v6);
v4 = RuntimeAddString(v5, &prm_0123);     // "\'"
RuntimeMsgBox(v4);                        // Throws the complete message

So the valid site password is constructed character by character and appended to the "Congratulations" message.

Application Challenge #1 (UNIX)


Target: app1.unix.bin
Requirement: Find the password
Difficulty: easy

The UNIX version is compiled for FreeBSD which is... odd.

I just throw it in IDA and use the decompiler and here's what I got:
UNIX version, entry point, IDA disassemblyint __cdecl main(int argc, const char **argv, const char **envp) {
// trimmed
    
    v9 = &argc;
    std::string::string((std::string *)&v8);
    std::string::string((std::string *)&v7);
    std::string::operator=(&v7, "moo");
    std::operator>><char,std::char_traits<char>,std::allocator<char>>(&std::cin, &v8);
    s2 = (char *)std::string::c_str((std::string *)&v7);
    v4 = (const char *)std::string::c_str((std::string *)&v8);
    if ( strcmp(v4, s2) == 0 ) {
        std::operator<<<std::char_traits<char>>(&std::cout, "IVannaHackHTS");
        v6 = 0;
    } else {
        v6 = 77;
    }
    std::string::~string((std::string *)&v7);
    std::string::~string((std::string *)&v8);
    return v6;
}

Couldn't be simpler than that: if the user entered code is "moo", it prints the site password "IVannaHackHTS"

Application Challenge #1 (Mac)


Target: app1mac
Requirement: Find the password
Difficulty: easy

I tried literally everything, including trying it on a genuine Mac, and yet I wasn't even able to extract the .sit file.
That being said - fuck Mac and fuck Apple.

Application Challenge #2 (Windows)


Target: app2win.exe
Requirement: Find the Password
Difficulty: easy

The second challenge looks pretty much like the first one:


Again it's a executable written in REALbasic, so you can refer to the first solution for more details.
Using the Python script in IDA, I'll fast forward to here:
OVERLAY entry point, IDA decompileint main_overlay() {
    RuntimeInit();
    sub_56F4E0();
    RuntimeRegisterFileType(&prm_0002, &prm_0001, &prm_0000, 0);
    sub_56F083();
    sub_56F35D();
    RuntimeRun();
    var_0001 = 0;
    RuntimeUnlockObject(0);
    RuntimeExit();
    return 0;
}

Same construction as before, and again I'm interested in the procedure right before RuntimeRun() - sub_56F35D():
OVERLAY_EP->sub_56F35D(), IDA decompileint sub_56F35D() {
// trimmed

    RuntimeStackCheck();
    RuntimeUnlockObject(0);
    v2 = sub_56AE2B();
    if ( !v2 )
        RuntimeNilObject();
    WindowForceUpdateFrontBuffer(v2);
    RuntimeUnlockObject(v2);
    return 0;
}

Continuing to sub_56AE2B():
OVERLAY_EP->sub_56F35D()->sub_56AE2B(), IDA decompileint sub_56AE2B() {
// trimmed

    RuntimeStackCheck();
    RuntimeUnlockObject(0);
    RuntimeLockUnlockObjects(0, 0);
    RuntimeUnlockObject(0);
    v0 = sub_5647EB(&prm_0169);
    v6 = RuntimeNewObject(v0);
    WindowDefaultConstructor(v6);
    RuntimeLockUnlockObjects(v6, 0);
    RuntimeUnlockObject(0);
    v1 = sub_5647EB(v4);
    v5 = RuntimeCheckCast(v6, v1);
    RuntimeLockObject(v5);
    RuntimeUnlockObject(v6);
    RuntimeUnlockObject(0);
    RuntimeUnlockObject(v6);
    RuntimeUnlockObject(v5);
    return v5;
}

and finally sub_5647EB():
OVERLAY_EP->sub_56F35D()->sub_56AE2B()->sub_5647EB(), IDA decompileint sub_5647EB() {
// trimmed

    RuntimeStackCheck();
    if (!var_0043) {
        v0 = RuntimeLookupClass(&prm_0110);           // "Window"
        var_0043 = RuntimeNewClass(v0, 18, 0, 21);
        *(_DWORD *)(var_0043 + 4) = &prm_0169;        // "Window1"
        RuntimeLockString(&prm_0169);
        v1 = var_0043;
        *(_DWORD *)(var_0043 + 16) = 0;
        *(_DWORD *)(v1 + 12) = 140;
        *(_DWORD *)(v1 + 20) = &unk_5647AD;
        *(_DWORD *)(v1 + 24) = &unk_5647CC;
        v2 = *(_DWORD *)(v1 + 32);
        *(_DWORD *)v2 = &unk_564ED8;
        *(_DWORD *)(v2 + 4) = &prm_0112;              // "#Layout%%o<Window1>"
        RuntimeLockString(&prm_0112);
        *(_DWORD *)(v2 + 8) = aUlBF;
        *(_DWORD *)(v2 + 12) = &prm_0113;             // "#CreateControls%%o<Window1>"
        RuntimeLockString(&prm_0113);
        *(_DWORD *)(v2 + 16) = &unk_56606E;
        *(_DWORD *)(v2 + 20) = &prm_0114;             // "StaticText1%o<StaticText>%o<Window1>"
        RuntimeLockString(&prm_0114);
        *(_DWORD *)(v2 + 24) = &unk_566345;           // / The serial number EDIT control
        *(_DWORD *)(v2 + 28) = &prm_0115;             // \ "key%o<EditField>%o<Window1>"
        RuntimeLockString(&prm_0115);
        *(_DWORD *)(v2 + 32) = &unk_56661C;
        *(_DWORD *)(v2 + 36) = &prm_0116;             // "StaticText2%o<StaticText>%o<Window1>"
        RuntimeLockString(&prm_0116);
        *(_DWORD *)(v2 + 40) = &unk_5668F3;
        *(_DWORD *)(v2 + 44) = &prm_0117;             // "PushButton1%o<PushButton>%o<Window1>"
        RuntimeLockString(&prm_0117);
        *(_DWORD *)(v2 + 48) = sub_566BCA;            // / Pressed BUTTON action
        *(_DWORD *)(v2 + 52) = &prm_0118;             // \ "PushButton1_Action%%o<Window1>o<PushButton>"
        RuntimeLockString(&prm_0118);
        *(_DWORD *)(v2 + 56) = &unk_566F60;
        *(_DWORD *)(v2 + 60) = &prm_0119;             // "status%o<StaticText>%o<Window1>"
        RuntimeLockString(&prm_0119);
        *(_DWORD *)(v2 + 64) = &unk_567237;           // / Init a SOCKET method
        *(_DWORD *)(v2 + 68) = &prm_0120;             // \ "Socket1%o<Socket>%o<Window1>"
        RuntimeLockString(&prm_0120);
        *(_DWORD *)(v2 + 72) = sub_56750E;            // / Read SOCKET data
        *(_DWORD *)(v2 + 76) = &prm_0121;             // \ "Socket1_DataAvailable%%o<Window1>o<Socket>"
        RuntimeLockString(&prm_0121);
        *(_DWORD *)(v2 + 80) = aUlB_;                 // / Connect SOCKET
        *(_DWORD *)(v2 + 84) = &prm_0122;             // \ "Socket1_Connected%%o<Window1>o<Socket>"
        RuntimeLockString(&prm_0122);
        *(_DWORD *)(v2 + 88) = &unk_569594;
        *(_DWORD *)(v2 + 92) = &prm_0123;             // "StaticText3%o<StaticText>%o<Window1>"
        RuntimeLockString(&prm_0123);
        *(_DWORD *)(v2 + 96) = &unk_56986B;
        *(_DWORD *)(v2 + 100) = &prm_0124;            // "EditUndo%o<MenuItem>%o<Window1>"
        RuntimeLockString(&prm_0124);
        *(_DWORD *)(v2 + 104) = &unk_569C0B;
        *(_DWORD *)(v2 + 108) = &prm_0125;            // "EditCut%o<MenuItem>%o<Window1>"
        RuntimeLockString(&prm_0125);
        *(_DWORD *)(v2 + 112) = &unk_569FAB;
        *(_DWORD *)(v2 + 116) = &prm_0126;            // "EditCopy%o<MenuItem>%o<Window1>"
        RuntimeLockString(&prm_0126);
        *(_DWORD *)(v2 + 120) = &unk_56A34B;
        *(_DWORD *)(v2 + 124) = &prm_0127;            // "EditPaste%o<MenuItem>%o<Window1>"
        RuntimeLockString(&prm_0127);
        *(_DWORD *)(v2 + 128) = &unk_56A6EB;
        *(_DWORD *)(v2 + 132) = &prm_0128;            // "EditClear%o<MenuItem>%o<Window1>"
        RuntimeLockString(&prm_0128);
        *(_DWORD *)(v2 + 136) = &unk_56AA8B;
        *(_DWORD *)(v2 + 140) = &prm_0129;            // "FileQuit%o<QuitMenuItem>%o<Window1>"
        RuntimeLockString(&prm_0129);
        v3 = *(_DWORD *)(var_0043 + 40);
        *(_DWORD *)v3 = &unk_564ED8;
        *(_DWORD *)(v3 + 4) = &prm_0130;              // "Layout"
        RuntimeLockString(&prm_0130);
        *(_DWORD *)(v3 + 8) = aUlBF;
        *(_DWORD *)(v3 + 12) = &prm_0131;             // "CreateControls"
        RuntimeLockString(&prm_0131);
    }
    return var_0043;
}

Alright, seems there's more than one places I should look.
First, as most obvious will be the button action prm_0118, associated with sub_566BCA():
sub_566BCA(prm_0118), IDA decompileint __cdecl sub_566BCA(int a1, int a2) {
    RuntimeLockObject(a1);
    RuntimeLockObject(a2);
    RuntimeStackCheck();
    RuntimeUnlockObject(0);
    v5 = (*(int (__cdecl **)(int))(*(_DWORD *)(a1 + 4) + 56))(a1);
    if ( !v5 )
        RuntimeNilObject();
    staticCaptionSetter(v5, 112, &prm_0141);                    // "Status: Connecting..."
    RuntimeUnlockObject(0);
    v4 = (*(int (__cdecl **)(int))(*(_DWORD *)(a1 + 4) + 64))(a1);
    if ( !v4 )
        RuntimeNilObject();
    SocketConnect(v4);

// trimmed

    return 0;
}

Nothing interesting here, so moving on.
prm_0120 is where the SOCKET is initialized and that's not interesting, so let's see the next one prm_0121 where the socket data is received - procedure sub_56750E():
sub_56750E(prm_0121), IDA decompileint __cdecl sub_56750E(int a1, int a2) {
    // trimmed
    RuntimeLockObject(a1);
    RuntimeLockObject(a2);
    RuntimeStackCheck();
    RuntimeUnlockString(0);
    if ( !a2 )
        RuntimeNilObject();
    v35 = SocketReadAll(a2);                                               // Read the socket reply data
    RuntimeLockUnlockStrings(v35, 0);
    RuntimeUnlockObject(0);
    v34 = (*(int (__cdecl **)(int))(*(_DWORD *)(a1 + 4) + 56))(a1);
    if ( !v34 )
      RuntimeNilObject();
    staticCaptionSetter(v34, 112, &prm_0146);                              // 'Status: Reading data...'
    RuntimeUnlockString(0);
    RuntimeUnlockObject(0);
    v33 = (*(int (__cdecl **)(int))(*(_DWORD *)(a1 + 4) + 24))(a1);
    if ( !v33 )
        RuntimeNilObject();
    v32 = editTextGetter(v33);
    if (!StringInStr(0, v35, v32))        // check if the user code is contained in the data read from the socket
        goto LABEL_28;
    RuntimeUnlockString(0);
    RuntimeUnlockObject(0);
    v31 = (*(int (__cdecl **)(int))(*(_DWORD *)(a1 + 4) + 24))(a1);
    if ( !v31 )
        RuntimeNilObject();
    v30 = editTextGetter(v31);
    if ( StringDBCSLen(v30) == 23 )                                        // valid code should be 23 characters long
        v29 = 1;
    else
        LABEL_28:
    v29 = 0;
    if (v29) {                                                             // at this point the code is verified
        RuntimeUnlockObject(0);
        v28 = (*(int (__cdecl **)(int))(*(_DWORD *)(a1 + 4) + 56))(a1);
        if ( !v28 )
            RuntimeNilObject();
        staticCaptionSetter(v28, 112, &prm_0147);                          // 'Status: Validated'

        // trimmed RuntimeUnlockString(0);

        v27 = StringDBCSChr(108);                                          // 'l'
        v26 = RuntimeAddString(&prm_0148, v27);                            // "Congratulations! The password to this level is \'"
        RuntimeUnlockString(0);
        v25 = StringDBCSChr(105);                                          // 'i'
        v24 = RuntimeAddString(v26, v25);
        RuntimeUnlockString(0);
        v23 = StringDBCSChr(98);                                           // 'b'
        v22 = RuntimeAddString(v24, v23);
        RuntimeUnlockString(0);
        v21 = StringDBCSChr(101);                                          // 'e'
        v20 = RuntimeAddString(v22, v21);
        RuntimeUnlockString(0);
        v19 = StringDBCSChr(114);                                          // 'r'
        v18 = RuntimeAddString(v20, v19);
        RuntimeUnlockString(0);
        v17 = StringDBCSChr(97);                                           // 'a'
        v16 = RuntimeAddString(v18, v17);
        RuntimeUnlockString(0);
        v15 = StringDBCSChr(116);                                          // 't'
        v14 = RuntimeAddString(v16, v15);
        RuntimeUnlockString(0);
        v13 = StringDBCSChr(105);                                          // 'i'
        v12 = RuntimeAddString(v14, v13);
        RuntimeUnlockString(0);
        v11 = StringDBCSChr(111);                                          // 'o'
        v10 = RuntimeAddString(v12, v11);
        RuntimeUnlockString(0);
        v9 = StringDBCSChr(110);                                           // 'n'
        v8 = RuntimeAddString(v10, v9);
        v7 = RuntimeAddString(v8, &prm_0149);
        RuntimeMsgBox(v7);                                                 // "\'"
        RuntimeUnlockObject(0);
        v6 = (*(int (__cdecl **)(int))(*(_DWORD *)(a1 + 4) + 64))(a1);
        if ( !v6 )
            RuntimeNilObject();
        socketClose(v6);
    } else {
        RuntimeUnlockObject(0);
        v5 = (*(int (__cdecl **)(_DWORD))(*(_DWORD *)(a1 + 4) + 56))(a1);
        if ( !v5 )
            RuntimeNilObject();
        staticCaptionSetter(v5, 112, &prm_0150);     // "Status: Serial invalid"
        RuntimeMsgBox(&prm_0151);                    // "Sorry, you entered an incorrect serial number. Please re-enter"
        RuntimeUnlockObject(0);
        v4 = (*(int (__cdecl **)(int))(*(_DWORD *)(a1 + 4) + 64))(a1);
        if ( !v4 )
            RuntimeNilObject();
        socketClose(v4);
    }

    // trimmed release functions

    return 0;
}

Alright I got the validation code and I got the correct password for the site - "liberation".
But where are the valid codes pulled from? I know it's a socket request, so let's see the socket connection procedure - prm_0122 and sub_568DD6():
sub_568DD6(prm_0122), IDA decompileint __cdecl sub_568DD6(int a1, int a2) {
    RuntimeLockObject(a1);
    RuntimeLockObject(a2);
    RuntimeStackCheck();
    RuntimeUnlockObject(0);
    v12 = (*(int (__cdecl **)(int))(*(_DWORD *)(a1 + 4) + 56))(a1);
    if ( !v12 )
        RuntimeNilObject();
    staticCaptionSetter(v12, 112, &prm_0152);                            // 'Status: Sending request...'
    RuntimeUnlockObject(0);
    v11 = (*(int (__cdecl **)(int))(*(_DWORD *)(a1 + 4) + 64))(a1);
    if ( !v11 )
        RuntimeNilObject();
    RuntimeUnlockString(0);
    RuntimeUnlockString(0);
    RuntimeUnlockString(0);
    RuntimeUnlockString(0);
    RuntimeUnlockString(0);
    v2 = StringDBCSChr(10);
    v3 = RuntimeAddString(&prm_0153, v2);                                // "GET /application/app2/keys123.txt HTTP/1.1"
    v4 = RuntimeAddString(v3, &prm_0154);                                // "Host: hackthissite.org"
    RuntimeUnlockString(0);
    v5 = StringDBCSChr(10);                                              // '\n'
    v6 = RuntimeAddString(v4, v5);
    RuntimeUnlockString(0);
    v7 = StringDBCSChr(10);                                              // '\n'
    v8 = RuntimeAddString(v6, v7);
    SocketWrite(v11, v8);

    // trimmed

    return 0;
}

A HTTP GET request builder.
The list of codes is located at http://hackthissite.org/application/app2/keys123.txt and it contains these valid codes:
valid user codes63482-74819-88456-98378
45910-18394-85113-51290
10110-19101-59111-41563
11424-74719-19578-99238
25182-28381-85611-85258
62351-12939-12481-58020
63482-74819-88456-98378
45910-18394-85113-51290
18381-21931-98680-86523
32910-21944-12391-51939
12389-16781-72893-71892
83478-91933-89823-98511

Trying any of these will work:


Application Challenge #2 (Mac)


Target: app2mac
Requirement: Find the Password
Difficulty: easy

Again, non-working Stuffit archive.

Application Challenge #3 (Windows)


Target: app3win.exe
Requirement: Find the Password
Difficulty: easy

The third challenge is again written in REALbasic and it looks like this:


This one actually is currently broken, but first things first.

Using the know-how from the previous challenges, that were also written in REALbasic, I can fast forward to the window create and process code:
sub_5647B4(), IDA decompileint sub_5647B4() {
    RuntimeStackCheck();
    if ( !var_0043 ) {
        v0 = RuntimeLookupClass(&prm_0110);             // "Window"
        var_0043 = RuntimeNewClass(v0, 18, 0, 21);
        *(_DWORD *)(var_0043 + 4) = &prm_0173;          // "Window1"
        RuntimeLockString(&prm_0173);                   // "Window1"
        v1 = var_0043;
        *(_DWORD *)(var_0043 + 16) = 0;
        *(_DWORD *)(v1 + 12) = 140;
        *(_DWORD *)(v1 + 20) = &unk_564776;
        *(_DWORD *)(v1 + 24) = &unk_564795;
        v2 = *(_DWORD *)(v1 + 32);
        *(_DWORD *)v2 = &unk_564EA1;
        *(_DWORD *)(v2 + 4) = &prm_0112;                 // "#Layout%%o<Window1>"
        RuntimeLockString(&prm_0112);
        *(_DWORD *)(v2 + 8) = aUlBF;
        *(_DWORD *)(v2 + 12) = &prm_0113;                // "#CreateControls%%o<Window1>"
        RuntimeLockString(&prm_0113);
        *(_DWORD *)(v2 + 16) = &unk_566037;
        *(_DWORD *)(v2 + 20) = &prm_0114;                // "StaticText1%o<StaticText>%o<Window1>"
        RuntimeLockString(&prm_0114);
        *(_DWORD *)(v2 + 24) = &unk_56630E;
        *(_DWORD *)(v2 + 28) = &prm_0115;                // "key%o<EditField>%o<Window1>"
        RuntimeLockString(&prm_0115);
        *(_DWORD *)(v2 + 32) = &unk_5665E5;
        *(_DWORD *)(v2 + 36) = &prm_0116;                // "StaticText2%o<StaticText>%o<Window1>"
        RuntimeLockString(&prm_0116);
        *(_DWORD *)(v2 + 40) = &unk_5668BC;
        *(_DWORD *)(v2 + 44) = &prm_0117;                // "PushButton1%o<PushButton>%o<Window1>"
        RuntimeLockString(&prm_0117);
        *(_DWORD *)(v2 + 48) = aUlB;
        *(_DWORD *)(v2 + 52) = &prm_0118;                // "PushButton1_Action%%o<Window1>o<PushButton>"
        RuntimeLockString(&prm_0118);
        *(_DWORD *)(v2 + 56) = &unk_566F29;
        *(_DWORD *)(v2 + 60) = &prm_0119;                // "status%o<StaticText>%o<Window1>"
        RuntimeLockString(&prm_0119);
        *(_DWORD *)(v2 + 64) = &unk_567200;
        *(_DWORD *)(v2 + 68) = &prm_0120;                // "Socket1%o<Socket>%o<Window1>"
        RuntimeLockString(&prm_0120);
        *(_DWORD *)(v2 + 72) = sub_5674D7;
        *(_DWORD *)(v2 + 76) = &prm_0121;                // "Socket1_DataAvailable%%o<Window1>o<Socket>"
        RuntimeLockString(&prm_0121);
        *(_DWORD *)(v2 + 80) = sub_568DFE;
        *(_DWORD *)(v2 + 84) = &prm_0122;                // "Socket1_Connected%%o<Window1>o<Socket>"
        RuntimeLockString(&prm_0122);
        *(_DWORD *)(v2 + 88) = &unk_56986F;
        *(_DWORD *)(v2 + 92) = &prm_0123;                // "StaticText3%o<StaticText>%o<Window1>"
        RuntimeLockString(&prm_0123);
        *(_DWORD *)(v2 + 96) = &unk_569B46;
        *(_DWORD *)(v2 + 100) = &prm_0124;               // "EditUndo%o<MenuItem>%o<Window1>"
        RuntimeLockString(&prm_0124);
        *(_DWORD *)(v2 + 104) = &unk_569EE6;
        *(_DWORD *)(v2 + 108) = &prm_0125;               // "EditCut%o<MenuItem>%o<Window1>"
        RuntimeLockString(&prm_0125);
        *(_DWORD *)(v2 + 112) = &unk_56A286;
        *(_DWORD *)(v2 + 116) = &prm_0126;               // "EditCopy%o<MenuItem>%o<Window1>"
        RuntimeLockString(&prm_0126);
        *(_DWORD *)(v2 + 120) = &unk_56A626;
        *(_DWORD *)(v2 + 124) = &prm_0127;               // "EditPaste%o<MenuItem>%o<Window1>"
        RuntimeLockString(&prm_0127);
        *(_DWORD *)(v2 + 128) = &unk_56A9C6;
        *(_DWORD *)(v2 + 132) = &prm_0128;               // "EditClear%o<MenuItem>%o<Window1>"
        RuntimeLockString(&prm_0128);
        *(_DWORD *)(v2 + 136) = &unk_56AD66;
        *(_DWORD *)(v2 + 140) = &prm_0129;               // "FileQuit%o<QuitMenuItem>%o<Window1>"
        RuntimeLockString(&prm_0129);
        v3 = *(_DWORD *)(var_0043 + 40);
        *(_DWORD *)v3 = &unk_564EA1;
        *(_DWORD *)(v3 + 4) = &prm_0130;
        RuntimeLockString(&prm_0130);                    // "Layout"
        *(_DWORD *)(v3 + 8) = aUlBF;
        *(_DWORD *)(v3 + 12) = &prm_0131;                // "CreateControls"
        RuntimeLockString(&prm_0131);
    }
    return var_0043;
}

Again sockets are involved, and I already have experience with those, so let's directly see what Socket1_DataAvailable at sub_5674D7() does:
Socket1_DataAvailable procedure, IDA decompileint __cdecl sub_5674D7(int a1, int a2) {
    // trimmed
    RuntimeLockObject(a1);
    RuntimeLockObject(a2);
    RuntimeStackCheck();
    RuntimeUnlockString(0);
    if ( !a2 )
        RuntimeNilObject();
    v35 = SocketReadAll(a2);
    RuntimeLockUnlockStrings(v35, 0);
    RuntimeUnlockObject(0);
    v34 = (*(int (__cdecl **)(int))(*(_DWORD *)(a1 + 4) + 56))(a1);
    if ( !v34 )
        RuntimeNilObject();
    staticCaptionSetter(v34, 112, &prm_0154);                               // "Status: Reading data..."
    if ( StringInStr(0, v35, &prm_0147) ) {                                 // is the server response "true" ?
        RuntimeUnlockObject(0);
        v33 = (*(int (__cdecl **)(int))(*(_DWORD *)(a1 + 4) + 56))(a1);
        if ( !v33 )
            RuntimeNilObject();
        staticCaptionSetter(v33, 112, &prm_0148);                           // "Status: Validated"
        // trimmed RuntimeUnlockString(0);
        v32 = StringDBCSChr(102);                                           // 'f'
        v31 = RuntimeAddString(&prm_0149, v32);                             // "Contratulations! The password to this level is \'"
        RuntimeUnlockString(0);
        v30 = StringDBCSChr(105);                                           // 'i'
        v29 = RuntimeAddString(v31, v30);
        RuntimeUnlockString(0);
        v28 = StringDBCSChr(114);                                           // 'r'
        v27 = RuntimeAddString(v29, v28);
        RuntimeUnlockString(0);
        v26 = StringDBCSChr(101);                                           // 'e'
        v25 = RuntimeAddString(v27, v26);
        RuntimeUnlockString(0);
        v24 = StringDBCSChr(121);                                           // 'y'
        v23 = RuntimeAddString(v25, v24);
        RuntimeUnlockString(0);
        v22 = StringDBCSChr(111);                                           // 'o'
        v21 = RuntimeAddString(v23, v22);
        RuntimeUnlockString(0);
        v20 = StringDBCSChr(117);                                           // 'u'
        v19 = RuntimeAddString(v21, v20);
        RuntimeUnlockString(0);
        v18 = StringDBCSChr(114);                                           // 'r'
        v17 = RuntimeAddString(v19, v18);
        RuntimeUnlockString(0);
        v16 = StringDBCSChr(98);                                            // 'b'
        v15 = RuntimeAddString(v17, v16);
        RuntimeUnlockString(0);
        v14 = StringDBCSChr(111);                                           // 'o'
        v13 = RuntimeAddString(v15, v14);
        RuntimeUnlockString(0);
        v12 = StringDBCSChr(115);                                           // 's'
        v11 = RuntimeAddString(v13, v12);
        RuntimeUnlockString(0);
        v10 = StringDBCSChr(115);                                           // 's'
        v9 = RuntimeAddString(v11, v10);
        v8 = RuntimeAddString(v9, &prm_0150);                               // "\'"
        RuntimeMsgBox(v8);
        RuntimeUnlockObject(0);
        v7 = (*(int (__cdecl **)(int))(*(_DWORD *)(a1 + 4) + 64))(a1);
        if ( !v7 )
            RuntimeNilObject();
        socketClose(v7);
    } else if ( StringInStr(0, v35, &prm_0151) ) {                          // is the server response "false" ?
        RuntimeUnlockObject(0);
        v6 = (*(int (__cdecl **)(_DWORD))(*(_DWORD *)(a1 + 4) + 56))(a1);
        if ( !v6 )
            RuntimeNilObject();
        staticCaptionSetter(v6, 112, &prm_0152);    // "Status: Serial invalid"
        RuntimeMsgBox(&prm_0153);                   // "Sorry, you entered an incorrect serial number. Please re-enter."
        RuntimeUnlockObject(0);
        v5 = (*(int (__cdecl **)(int))(*(_DWORD *)(a1 + 4) + 64))(a1);
        if ( !v5 )
            RuntimeNilObject();
        socketClose(v5);
    } else {
        RuntimeUnlockObject(0);
        v4 = (*(int (__cdecl **)(_DWORD))(*(_DWORD *)(a1 + 4) + 56))(a1);
        if ( !v4 )
            RuntimeNilObject();
        staticCaptionSetter(v4, 112, &prm_0154);                            // "Status: Reading data..."
    }
    // trimmed
    return 0;
}

I got the site's password again, but let's check the validation process.
The server response now is not a set of valid codes to be checked against the user entered code, but a boolean "true" or "false" value.
Let's see where's the validator URL, by checking Socket1_Connected procedure - sub_568DFE():
Socket1_Connected procedure, IDA decompileint __cdecl sub_568DFE(int a1, int a2) {
    // trimmed
    RuntimeLockObject(a1);
    RuntimeLockObject(a2);
    RuntimeStackCheck();
    RuntimeUnlockObject(0);
    v16 = (*(int (__cdecl **)(int))(*(_DWORD *)(a1 + 4) + 56))(a1);
    if ( !v16 )
        RuntimeNilObject();
    staticCaptionSetter(v16, 112, &prm_0155);                         // "Status: Sending request..."
    RuntimeUnlockObject(0);
    v15 = (*(int (__cdecl **)(int))(*(_DWORD *)(a1 + 4) + 64))(a1);
    if ( !v15 )
        RuntimeNilObject();
    // trimmed
    v14 = (*(int (__cdecl **)(int))(*(_DWORD *)(a1 + 4) + 24))(a1);
    if ( !v14 )
        RuntimeNilObject();
    v2 = editTextGetter(v14);
    v3 = RuntimeAddString(&prm_0156, v2);                             // "GET /missions/application/app3/auth.php?key="
    v4 = RuntimeAddString(v3, &prm_0157);                             // " HTTP/1.1"
    RuntimeUnlockString(0);
    v5 = StringDBCSChr(10);                                           // '\n'
    v6 = RuntimeAddString(v4, v5);
    v7 = RuntimeAddString(v6, &prm_0158);                             // "Host: hackthissite.org"
    RuntimeUnlockString(0);
    v8 = StringDBCSChr(10);                                           // '\n'
    v9 = RuntimeAddString(v7, v8);
    RuntimeUnlockString(0);
    v10 = StringDBCSChr(10);                                          // '\n'
    v11 = RuntimeAddString(v9, v10);
    SocketWrite(v15, v11);
    // trimmed
    return 0;
}

The HTTP request is now at http://hackthissite.org/missions/application/app3/auth.php?key=<user-key> and the response can be either "true" or "false".
However, when I click "Authenticate", the status gets stuck to "Status: Reading data...".
I fired up Wireshark to see what's going on, and here's what I got:
Request:0000   00 50 56 ea e8 4a 00 0c 29 58 d1 a4 08 00 45 00  .PV..J..)X....E.
0010   00 80 18 79 40 00 80 06 00 00 c0 a8 f1 9c c6 94  ...y@...........
0020   51 8b cb e7 00 50 e4 c2 5a ad 25 73 1b 68 50 18  Q....P..Z.%s.hP.
0030   fa f0 ca d7 00 00 47 45 54 20 2f 6d 69 73 73 69  ......GET /missi
0040   6f 6e 73 2f 61 70 70 6c 69 63 61 74 69 6f 6e 2f  ons/application/
0050   61 70 70 33 2f 61 75 74 68 2e 70 68 70 3f 6b 65  app3/auth.php?ke
0060   79 3d 00 31 32 33 31 32 33 31 32 33 20 48 54 54  y=.123123123 HTT
0070   50 2f 31 2e 31 0a 48 6f 73 74 3a 20 68 61 63 6b  P/1.1.Host: hack
0080   74 68 69 73 73 69 74 65 2e 6f 72 67 0a 0a        thissite.org..
What is this \x00 doing there?

Response:0000   00 0c 29 58 d1 a4 00 50 56 ea e8 4a 08 00 45 00  ..)X...PV..J..E.
0010   00 ce 3c 66 00 00 80 06 33 5f c6 94 51 8b c0 a8  ..<f....3_..Q...
0020   f1 9c 00 50 cb e7 25 73 1b 68 e4 c2 5b 05 50 18  ...P..%s.h..[.P.
0030   fa f0 0a af 00 00 3c 68 74 6d 6c 3e 0d 0a 3c 68  ......<html>..<h
0040   65 61 64 3e 3c 74 69 74 6c 65 3e 34 30 30 20 42  ead><title>400 B
0050   61 64 20 52 65 71 75 65 73 74 3c 2f 74 69 74 6c  ad Request</titl
0060   65 3e 3c 2f 68 65 61 64 3e 0d 0a 3c 62 6f 64 79  e></head>..<body
0070   20 62 67 63 6f 6c 6f 72 3d 22 77 68 69 74 65 22   bgcolor="white"
0080   3e 0d 0a 3c 63 65 6e 74 65 72 3e 3c 68 31 3e 34  >..<center><h1>4
0090   30 30 20 42 61 64 20 52 65 71 75 65 73 74 3c 2f  00 Bad Request</
00a0   68 31 3e 3c 2f 63 65 6e 74 65 72 3e 0d 0a 3c 68  h1></center>..<h
00b0   72 3e 3c 63 65 6e 74 65 72 3e 6e 67 69 6e 78 3c  r><center>nginx<
00c0   2f 63 65 6e 74 65 72 3e 0d 0a 3c 2f 62 6f 64 79  /center>..</body
00d0   3e 0d 0a 3c 2f 68 74 6d 6c 3e 0d 0a              >..</html>..

Boom. Ok, let's see the string inside the code:
prm_0156, IDA disassemblyOVERLAY:005709F8 prm_0156        struc_PRM <1, offset str_0156, 2Fh, 2Dh, 8000100h>
OVERLAY:00570A0C str_0156        db 45,'GET /missions/application/app3/auth.php?key=',0,0,0

The string itself is 44 bytes long, but the length is set to 45 (i actually need to change the 0x2D in the prm_0156 structure only). Seriously? It's buggy already?
Alright, I can easily patch this in HxD and try again, using my bad pass:
Request:0000   00 50 56 ea e8 4a 00 0c 29 58 d1 a4 08 00 45 00  .PV..J..)X....E.
0010   00 7f 0b 71 40 00 80 06 00 00 c0 a8 f1 9c c6 94  ...q@...........
0020   51 89 c0 81 00 50 39 23 fb ad 5e 5c 5c 89 50 18  Q....P9#..^\\.P.
0030   fa f0 ca d4 00 00 47 45 54 20 2f 6d 69 73 73 69  ......GET /missi
0040   6f 6e 73 2f 61 70 70 6c 69 63 61 74 69 6f 6e 2f  ons/application/
0050   61 70 70 33 2f 61 75 74 68 2e 70 68 70 3f 6b 65  app3/auth.php?ke
0060   79 3d 31 32 33 31 32 33 31 32 33 20 48 54 54 50  y=123123123 HTTP
0070   2f 31 2e 31 0a 48 6f 73 74 3a 20 68 61 63 6b 74  /1.1.Host: hackt
0080   68 69 73 73 69 74 65 2e 6f 72 67 0a 0a           hissite.org..

Ok, that looks better.
Response:0000   00 0c 29 58 d1 a4 00 50 56 ea e8 4a 08 00 45 00  ..)X...PV..J..E.
0010   02 cb 3d d6 00 00 80 06 2f f4 c6 94 51 89 c0 a8  ..=...../...Q...
0020   f1 9c 00 50 c0 81 5e 5c 5c 89 39 23 fc 04 50 18  ...P..^\\.9#..P.
0030   fa f0 d3 8e 00 00 48 54 54 50 2f 31 2e 31 20 33  ......HTTP/1.1 3
0040   30 31 20 4d 6f 76 65 64 20 50 65 72 6d 61 6e 65  01 Moved Permane
0050   6e 74 6c 79 0d 0a 44 61 74 65 3a 20 57 65 64 2c  ntly..Date: Wed,
0060   20 31 39 20 4a 75 6c 20 32 30 31 37 20 31 38 3a   19 Jul 2017 18:
0070   33 33 3a 32 31 20 47 4d 54 0d 0a 43 6f 6e 74 65  33:21 GMT..Conte
0080   6e 74 2d 54 79 70 65 3a 20 74 65 78 74 2f 68 74  nt-Type: text/ht
0090   6d 6c 3b 20 63 68 61 72 73 65 74 3d 69 73 6f 2d  ml; charset=iso-
00a0   38 38 35 39 2d 31 0d 0a 43 6f 6e 74 65 6e 74 2d  8859-1..Content-
00b0   4c 65 6e 67 74 68 3a 20 32 38 34 0d 0a 43 6f 6e  Length: 284..Con
00c0   6e 65 63 74 69 6f 6e 3a 20 6b 65 65 70 2d 61 6c  nection: keep-al
00d0   69 76 65 0d 0a 4c 6f 63 61 74 69 6f 6e 3a 20 68  ive..Location: h
00e0   74 74 70 3a 2f 2f 77 77 77 2e 68 61 63 6b 74 68  ttp://www.hackth
00f0   69 73 73 69 74 65 2e 6f 72 67 2f 6d 69 73 73 69  issite.org/missi
0100   6f 6e 73 2f 61 70 70 6c 69 63 61 74 69 6f 6e 2f  ons/application/
0110   61 70 70 33 2f 61 75 74 68 2e 70 68 70 3f 6b 65  app3/auth.php?ke
0120   79 3d 31 32 33 31 32 33 31 32 33 0d 0a 53 65 72  y=123123123..Ser
0130   76 65 72 3a 20 48 61 63 6b 54 68 69 73 53 69 74  ver: HackThisSit
0140   65 20 4c 6f 61 64 20 42 61 6c 61 6e 63 65 72 0d  e Load Balancer.
0150   0a 53 74 72 69 63 74 2d 54 72 61 6e 73 70 6f 72  .Strict-Transpor
0160   74 2d 53 65 63 75 72 69 74 79 3a 20 6d 61 78 2d  t-Security: max-
0170   61 67 65 3d 33 31 35 33 36 30 30 30 3b 20 69 6e  age=31536000; in
0180   63 6c 75 64 65 53 75 62 64 6f 6d 61 69 6e 73 3b  cludeSubdomains;
0190   20 70 72 65 6c 6f 61 64 0d 0a 58 2d 43 6f 6e 74   preload..X-Cont
01a0   65 6e 74 2d 54 79 70 65 2d 4f 70 74 69 6f 6e 73  ent-Type-Options
01b0   3a 20 6e 6f 73 6e 69 66 66 0d 0a 0d 0a 3c 21 44  : nosniff....<!D
01c0   4f 43 54 59 50 45 20 48 54 4d 4c 20 50 55 42 4c  OCTYPE HTML PUBL
01d0   49 43 20 22 2d 2f 2f 49 45 54 46 2f 2f 44 54 44  IC "-//IETF//DTD
01e0   20 48 54 4d 4c 20 32 2e 30 2f 2f 45 4e 22 3e 0a   HTML 2.0//EN">.
01f0   3c 68 74 6d 6c 3e 3c 68 65 61 64 3e 0a 3c 74 69  <html><head>.<ti
0200   74 6c 65 3e 33 30 31 20 4d 6f 76 65 64 20 50 65  tle>301 Moved Pe
0210   72 6d 61 6e 65 6e 74 6c 79 3c 2f 74 69 74 6c 65  rmanently</title
0220   3e 0a 3c 2f 68 65 61 64 3e 3c 62 6f 64 79 3e 0a  >.</head><body>.
0230   3c 68 31 3e 4d 6f 76 65 64 20 50 65 72 6d 61 6e  <h1>Moved Perman
0240   65 6e 74 6c 79 3c 2f 68 31 3e 0a 3c 70 3e 54 68  ently</h1>.<p>Th
0250   65 20 64 6f 63 75 6d 65 6e 74 20 68 61 73 20 6d  e document has m
0260   6f 76 65 64 20 3c 61 20 68 72 65 66 3d 22 68 74  oved <a href="ht
0270   74 70 3a 2f 2f 77 77 77 2e 68 61 63 6b 74 68 69  tp://www.hackthi
0280   73 73 69 74 65 2e 6f 72 67 2f 6d 69 73 73 69 6f  ssite.org/missio
0290   6e 73 2f 61 70 70 6c 69 63 61 74 69 6f 6e 2f 61  ns/application/a
02a0   70 70 33 2f 61 75 74 68 2e 70 68 70 3f 6b 65 79  pp3/auth.php?key
02b0   3d 31 32 33 31 32 33 31 32 33 22 3e 68 65 72 65  =123123123">here
02c0   3c 2f 61 3e 2e 3c 2f 70 3e 0a 3c 2f 62 6f 64 79  </a>.</p>.</body
02d0   3e 3c 2f 68 74 6d 6c 3e 0a                       ></html>.

Oh for fucks sake, really? Now i need to change the domain and add "www." in front of it.
But how:
prm_0158, IDA disassemblyOVERLAY:00570A5C prm_0158        struc_PRM <1, offset str_0158, 18h, 16h, 8000100h>
OVERLAY:00570A70 str_0158        db 22,'Host: hackthissite.org',0

I need to add 4 bytes more, but there's not enough space in here... decisions, decisions.

Can't lie, I fiddle for a hour thinking of a elegant solution for this. In the end, I just updated the string, overwriting the next parameter, crossed fingers and gave it a try:


Damn, that actually worked without crash!
It's a shit solution, but it's also a working solution.

Now, I know I already got the password for the site, but why not try to fool the app, that any password is correct?
prm_0147 and prm_0151, IDA disassemblyOVERLAY:00570884 prm_0147        struc_PRM <1, offset str_0147, 6, 4, 8000100h>
OVERLAY:00570898 str_0147        db 4,'true',0,0,0
; trimmed
OVERLAY:00570928 prm_0151        struc_PRM <1, offset str_0151, 7, 5, 8000100h>
OVERLAY:0057093C str_0151        db 5,'false',0,0

Due to the dword alignment, there's enough space to flip that "true" to "false" and make the bad passwords valid, so let's give it a try:


Nice, challenge #3 is officially completed.

Application Challenge #3 (Mac)


Target: app3win.sit
Requirement: Find the Password
Difficulty: easy

And yet again, broken Stuffit archive.

Application Challenge #4 (Windows)


Target: app4win.exe
Requirement: Press the Button
Difficulty: easy

Here's what I got here:


Trying to focus on a button disables the pointed one and enables the other.
According to DiE, this challenge is written in VisualBasic:


That's fine. A standard way to enable and disable controls is using the EnableWindow() API function, so I'll set a breakpoint on it in x86dbg and try to point a button:
EnableWindow(), x86dbg75A58D02 | 8B FF             | mov edi,edi                ; EnableWindow entry point
75A58D04 | 55                | push ebp
75A58D05 | 8B EC             | mov ebp,esp
75A58D07 | 6A 62             | push 62
75A58D09 | FF 75 0C          | push dword ptr ss:[ebp+C]
75A58D0C | FF 75 08          | push dword ptr ss:[ebp+8]
75A58D0F | E8 BD 18 00 00    | call user32.75A5A5D1
75A58D14 | 5D                | pop ebp
75A58D15 | C2 08 00          | ret 8

This is a breakpoint inside kernel32.dll, so now I need to execute until RET instruction, so I end up in the app4win.exe, which is here:
EnableWindow(), x86dbg0040286D | 8B F8                | mov edi,eax
0040286F | 6A 00                | push 0
00402871 | 57                   | push edi
00402872 | 8B 0F                | mov ecx,dword ptr ds:[edi]
00402874 | FF 91 8C 00 00 00    | call dword ptr ds:[ecx+8C]    ; Call to a msvbvm60.dll wrapper over EnableWindow
0040287A | 85 C0                | test eax,eax
0040287C | DB E2                | fnclex
0040287E | 7D 12                | jge app4win.402892

That PUSH 0 looks promising, so I'll flip it to 1 and see what's going to happen:


Alright, that made the upper button to be permanently enabled but now I can't click it.
So there must be something I'm missing here. Back tracing the code upwards in IDA led me here:
IDA disassembly.text:00402590 loc_402590:                                              ; back trace to here
.text:00402590                 push    ebp
.text:00402591                 mov     ebp, esp
.text:00402593                 sub     esp, 0Ch
.text:00402596                 push    offset __vbaExceptHandler
.text:0040259B                 mov     eax, large fs:0
; more code
.text:0040247C loc_40247C:
.text:0040247C                 sub     dword ptr [esp+4], 33h           ; Create main window
.text:00402484                 jmp     loc_402590                       ; Back traced to here
.text:00402489 loc_402489:
.text:00402489                 sub     dword ptr [esp+4], 37h           ; unknown
.text:00402491                 jmp     loc_402750
.text:00402496 loc_402496:
.text:00402496                 sub     dword ptr [esp+4], 37h           ; Disable upper button
.text:0040249E                 jmp     loc_402810
.text:004024A3 loc_4024A3:
.text:004024A3                 sub     dword ptr [esp+4], 3Bh           ; unknown
.text:004024AB                 jmp     loc_402910
.text:004024B0 loc_4024B0:
.text:004024B0                 sub     dword ptr [esp+4], 3Bh           ; Disable lower button
.text:004024B8                 jmp     loc_4029D0
.text:004024BD loc_4024BD:
.text:004024BD                 sub     dword ptr [esp+4], 37h           ; unknown
.text:004024C5                 jmp     loc_402AD0
.text:004024CA loc_4024CA:
.text:004024CA                 sub     dword ptr [esp+4], 3Bh           ; unknown
.text:004024D2                 jmp     loc_403170

That looks like a event switch or something.
I've set breakpoints on these and it turns out that 0x33 is triggered when creating the main window, while 0x37 (addr 00402496) and 0x3B (addr 004024B0) are triggered when pointing the upper and respectively the bottom buttons.
The rest are unknown, so what can I do here? I can change the JMP of a button pointing to one of the unknown jumps, so I change that JMP loc_402810 to JMP loc_402750.

Now the upper button is permanently enabled. The event at 004024A3 does the same, but for the bottom button.
So, only the events at 004024BD and 004024CA are unknown. Doing the same trick, I changed the JMP loc_402810 to JMP loc_402AD0 and here's the result:


Nice, I've relocated the event that originally hide the upper button to act as if the upper button is pressed and that way I got the site's password.
So the events at 004024BD and 004024CA are handling the button press events.
Knowing that, I can now check where the site's password is constructed, by following that JMP loc_402AD0:
Site code construction ,IDA disassembly.text:00402B12                 mov     edi, ds:rtcVarBstrFromAnsi
.text:00402B18                 lea     eax, [ebp+var_28]
.text:00402B1B                 xor     esi, esi
.text:00402B1D                 push    'P'
.text:00402B1F                 push    eax
; trimmed
.text:00402C19                 call    edi ; rtcVarBstrFromAnsi
.text:00402C1B                 lea     ecx, [ebp+var_38]
.text:00402C1E                 push    'a'
.text:00402C20                 push    ecx
.text:00402C21                 call    edi ; rtcVarBstrFromAnsi
.text:00402C23                 lea     edx, [ebp+var_58]
.text:00402C26                 push    's'
.text:00402C28                 push    edx
.text:00402C29                 call    edi ; rtcVarBstrFromAnsi
.text:00402C2B                 lea     eax, [ebp+var_78]
.text:00402C2E                 push    's'
.text:00402C30                 push    eax
.text:00402C31                 call    edi ; rtcVarBstrFromAnsi
.text:00402C33                 lea     ecx, [ebp+var_98]
.text:00402C39                 push    'w'
.text:00402C3B                 push    ecx
.text:00402C3C                 call    edi ; rtcVarBstrFromAnsi
.text:00402C3E                 lea     edx, [ebp+var_B8]
.text:00402C44                 push    'o'
.text:00402C46                 push    edx
.text:00402C47                 call    edi ; rtcVarBstrFromAnsi
.text:00402C49                 lea     eax, [ebp+var_D8]
.text:00402C4F                 push    'r'
.text:00402C51                 push    eax
.text:00402C52                 call    edi ; rtcVarBstrFromAnsi
.text:00402C54                 lea     ecx, [ebp+var_F8]
.text:00402C5A                 push    'd'
.text:00402C5C                 push    ecx
.text:00402C5D                 call    edi ; rtcVarBstrFromAnsi
.text:00402C5F                 lea     edx, [ebp+var_118]
.text:00402C65                 push    ' '
.text:00402C67                 push    edx
.text:00402C68                 call    edi ; rtcVarBstrFromAnsi
.text:00402C6A                 lea     eax, [ebp+var_138]
.text:00402C70                 push    'i'
.text:00402C72                 push    eax
.text:00402C73                 call    edi ; rtcVarBstrFromAnsi
.text:00402C75                 lea     ecx, [ebp+var_158]
.text:00402C7B                 push    's'
.text:00402C7D                 push    ecx
.text:00402C7E                 call    edi ; rtcVarBstrFromAnsi
.text:00402C80                 lea     edx, [ebp+var_178]
.text:00402C86                 push    ' '
.text:00402C88                 push    edx
.text:00402C89                 call    edi ; rtcVarBstrFromAnsi
.text:00402C8B                 lea     eax, [ebp+var_198]
.text:00402C91                 push    '\''
.text:00402C93                 push    eax
.text:00402C94                 call    edi ; rtcVarBstrFromAnsi
.text:00402C96                 lea     ecx, [ebp+var_1B8]
.text:00402C9C                 push    'd'
.text:00402C9E                 push    ecx
.text:00402C9F                 call    edi ; rtcVarBstrFromAnsi
.text:00402CA1                 lea     edx, [ebp+var_1D8]
.text:00402CA7                 push    'a'
.text:00402CA9                 push    edx
.text:00402CAA                 call    edi ; rtcVarBstrFromAnsi
.text:00402CAC                 lea     eax, [ebp+var_1F8]
.text:00402CB2                 push    'y'
.text:00402CB4                 push    eax
.text:00402CB5                 call    edi ; rtcVarBstrFromAnsi
.text:00402CB7                 lea     ecx, [ebp+var_218]
.text:00402CBD                 push    't'
.text:00402CBF                 push    ecx
.text:00402CC0                 call    edi ; rtcVarBstrFromAnsi
.text:00402CC2                 lea     edx, [ebp+var_238]
.text:00402CC8                 push    'o'
.text:00402CCA                 push    edx
.text:00402CCB                 call    edi ; rtcVarBstrFromAnsi
.text:00402CCD                 lea     eax, [ebp+var_258]
.text:00402CD3                 push    'n'
.text:00402CD5                 push    eax
.text:00402CD6                 call    edi ; rtcVarBstrFromAnsi
.text:00402CD8                 lea     ecx, [ebp+var_278]
.text:00402CDE                 push    'a'
.text:00402CE0                 push    ecx
.text:00402CE1                 call    edi ; rtcVarBstrFromAnsi
.text:00402CE3                 lea     edx, [ebp+var_298]
.text:00402CE9                 push    '\''
.text:00402CEB                 push    edx
.text:00402CEC                 call    edi ; rtcVarBstrFromAnsi
.text:00402CEE                 cmp     dword_404010, esi
.text:00402CF4                 jnz     short loc_402D06
.text:00402CF6                 push    offset dword_404010
.text:00402CFB                 push    offset dword_402198
.text:00402D00                 call    ds:__vbaNew2

So that's how the password message is generated. Challenge completed!

Application Challenge #5 (Windows)


Target: app5win.exe
Requirement: Find the password
Difficulty: easy

We have a C/C++ console application here:


I find myself using the IDA's decompiler quite often lately, but it's just so useful:
Entry point, IDA decompileint __cdecl main(int argc, const char **argv, const char **envp) {
// trimmed
    v8 = 0xA67;                                                   // / Those values look interesting
    v9 = 0x6E697070;                                              // |
    v10 = 0x69727472;                                             // |
    v11 = 0x65776F70;                                             // \
    puts(aPleaseEnterThe);
    memset(v4, 0, 0x10u);
    v7 = 0;
    v6 = 0;
    v5 = 0;
    do {
        v13 = j___fgetchar();                                     // Read the user input
        v4[v7++] = v13;
    } while(v13 != 0xA && v13 && v7 < 0x10);                      // Read until ENTER is pressed (0x0A char)
                                                                  // The user input should be less than 0x10 characters
    v12 = (int)v4;
    v6 = 0;
    v5 = 3;
    while (v6 < 0xD) {                                            // The loop is limited to 0x0D characters (3 DWORDS)
        if (*(_DWORD *)(v12 + 4 * (v6 >> 2)) != *(&v8 + v5)) {    // "v12 + 4" takes a chunk of the user code as DWORD
                                                                  // and compares it to v8
            printf(aInvalidPasswor);                              // Bad password message
            return 0;
        }
        v6 += 4;                                                  // The iteration is set to 4 bytes
        --v5;
    }
    printf(aThePasswordIsS, v4);                                  // The valid password for the site is the same as the user pass
    return 0;
}

IDA's decompiler is good, but not perfect, so referring to the assembler code can throw light on the whole picture:
Entry point, IDA disassembly00401086 | 8D 45 CC                | lea eax,dword ptr ss:[ebp-34]
00401089 | 89 45 F8                | mov dword ptr ss:[ebp-8],eax
0040108C | C7 45 E0 00 00 00 00    | mov dword ptr ss:[ebp-20],0
00401093 | C7 45 DC 03 00 00 00    | mov dword ptr ss:[ebp-24],3
0040109A | EB 12                   | jmp app5win.4010AE
0040109C | 8B 4D E0                | mov ecx,dword ptr ss:[ebp-20]
0040109F | 83 C1 04                | add ecx,4
004010A2 | 89 4D E0                | mov dword ptr ss:[ebp-20],ecx
004010A5 | 8B 55 DC                | mov edx,dword ptr ss:[ebp-24]      ;/ EDX is the correct pass iterator
004010A8 | 83 EA 01                | sub edx,1                          ;|
004010AB | 89 55 DC                | mov dword ptr ss:[ebp-24],edx      ;\
004010AE | 83 7D E0 0D             | cmp dword ptr ss:[ebp-20],D        ; The loop limit is set to 0x0D
004010B2 | 73 28                   | jae app5win.4010DC                 ; if the loop limit is reached, break the loop
004010B4 | 8B 45 E0                | mov eax,dword ptr ss:[ebp-20]      ;/ EAX is the user's pass iterator
004010B7 | C1 E8 02                | shr eax,2                          ;\
004010BA | 8B 4D F8                | mov ecx,dword ptr ss:[ebp-8]       ; ECX is the user's password - "123123123"
004010BD | 8B 55 DC                | mov edx,dword ptr ss:[ebp-24]
004010C0 | 8B 04 81                | mov eax,dword ptr ds:[ecx+eax*4]   ; Take a dword from the user code
004010C3 | 3B 44 95 E8             | cmp eax,dword ptr ss:[ebp+edx*4-18]; and compares it to this value and
004010C7 | 74 11                   | je app5win.4010DA                  ; if they are equal, jumps and continues to compare the rest of it
004010C9 | 68 4C 70 40 00          | push app5win.40704C                ; otherwise prints "Invalid Password"
004010CE | E8 20 00 00 00          | call app5win.4010F3                ; that's a printf()
004010D3 | 83 C4 04                | add esp,4
004010D6 | 33 C0                   | xor eax,eax
004010D8 | EB 15                   | jmp app5win.4010EF                 ; jump to program exit
004010DA | EB C0                   | jmp app5win.40109C                 ; loop jump
004010DC | 8D 4D CC                | lea ecx,dword ptr ss:[ebp-34]
004010DF | 51                      | push ecx                           ; ECX holds the user entered password - "123123123"
004010E0 | 68 60 70 40 00          | push app5win.407060                ; format for the next printf() call is "The password is %s\n"
004010E5 | E8 09 00 00 00          | call app5win.4010F3                ; printf()
004010EA | 83 C4 08                | add esp,8
004010ED | 33 C0                   | xor eax,eax
004010EF | 8B E5                   | mov esp,ebp
004010F1 | 5D                      | pop ebp
004010F2 | C3                      | ret                                ; program exit

So, the loop is limited to 0x0D, and with every iteration it compares a DWORD of the user's pass with a DWORD of something stored at [ebp+edx*4-18].
If the DWORD values doesn't match, the "Invalid Password" message is thrown.
This means, the loop will run four times (because 0x0D/sizeof(DWORD)=3+1), therefore the valid password is 13 bytes long, stored in whatever [ebp+edx*4-18] holds.
I can easily check this in x86dbg:
Code validation, IDA disassembly004010C0 | 8B 04 81                           | mov eax,dword ptr ds:[ecx+eax*4]
004010C3 | 3B 44 95 E8                        | cmp eax,dword ptr ss:[ebp+edx*4-18]    ; tracing up to here
004010C7 | 74 11                              | je app5win.4010DA

; EIP
; eax=31333231                                   ; my bad password's first DWORD 1231
; dword ptr[ebp+edx*4-18]=[0012FF3C]=65776F70    ; the correct password's first DWORD is located at 0x0012FF3C

; Memory
; 0012FF2C  0D 00 00 00 67 0A 00 00 70 70 69 6E 72 74 72 69  ....g...ppinrtri  
; 0012FF3C  70 6F 77 65 14 FF 12 00 0A 20 40 00 88 FF 12 00  powe.ÿ... @..ÿ..    ; it's plaintext!

So the three DWORDs of the correct password are "powe", "rtri", "ppin", "g\n\x00\x00", and trying "powertripping" as correct password gives me this:


Nice, challenge completed!

By the way, there's a light obfuscation thing, where the user password iterator is incremented by 4, but then it's shifted right by 2, thus ending as a simple 0, 1, 2, 3:
Obfuscation?, IDA disassembly0040109C | 8B 4D E0                | mov ecx,dword ptr ss:[ebp-20]       ;/ Increment the iterator by 4
0040109F | 83 C1 04                | add ecx,4                           ;|
004010A2 | 89 4D E0                | mov dword ptr ss:[ebp-20],ecx       ;\
; trimmed
004010B4 | 8B 45 E0                | mov eax,dword ptr ss:[ebp-20]       ;/ Shift it right by 2
004010B7 | C1 E8 02                | shr eax,2                           ;\ this is basically equal to divide by 4
; trimmed
004010C0 | 8B 04 81                | mov eax,dword ptr ds:[ecx+eax*4]    ; use it as times 4


Application Challenge #6 (Windows)


Target: app6win.exe
Requirement: Find the password
Difficulty: easy

Another console application written in VC++:


And the IDA disassembly:
Entry oint, IDA decompileint __cdecl main(int argc, const char **argv, const char **envp) {
    // trimmed
    VirtualQuery(&loc_4010D3, &Buffer, 0x1Cu);
    v3 = Buffer.Protect & 0xFFFFFFDD;
    LOBYTE(v3) = Buffer.Protect & 0xDD | 4;
    VirtualProtect(&loc_4010D3, 0xD0u, v3, &flOldProtect);
    v8 = (int)&loc_4010D3;
    for ( i = 0; i < 0x33; ++i )
        *(_DWORD *)(v8 + 4 * i) ^= 0xBEEFCABE;
    return ((int (__stdcall *)(int, DWORD, PVOID, PVOID, DWORD, SIZE_T, DWORD, DWORD, DWORD, int, unsigned int))loc_4010D3)(
        v5,
        flOldProtect,
        Buffer.BaseAddress,
        Buffer.AllocationBase,
        Buffer.AllocationProtect,
        Buffer.RegionSize,
        Buffer.State,
        Buffer.Protect,
        Buffer.Type,
        v8,
        i);
}

That XOR decryptor routine is so obvious...
If we look at the assembly code, there's some minor code obfuscation too:
Code obfuscation, IDA disassembly.text:00401056 loc_401056:
.text:00401056                 mov     eax, [ebp+var_4]     ;/ EAX is the iterator
.text:00401059                 add     eax, 1               ;|
.text:0040105C                 mov     [ebp+var_4], eax     ;\
.text:0040105F loc_40105F:
.text:0040105F                 cmp     [ebp+var_4], 33h     ; The encrypted block is only 0x33 bytes long
.text:00401063                 jnb     short loc_40107E
.text:00401065                 mov     ecx, [ebp+var_4]
.text:00401068                 mov     edx, [ebp+var_8]
.text:0040106B                 mov     eax, [edx+ecx*4]     ; take a DWORD of the encrypted code
.text:0040106E                 xor     eax, 0BEEFCABEh      ; XOR it with that key
.text:00401073                 mov     ecx, [ebp+var_4]
.text:00401076                 mov     edx, [ebp+var_8]
.text:00401079                 mov     [edx+ecx*4], eax     ; update the decrypted DWORD
.text:0040107C                 jmp     short loc_401056
.text:0040107E loc_40107E:
.text:0040107E                 nop                          ;/ NOP "obfuscation"
                                                            ;| trimmed
.text:004010C6                 nop                          ;\
.text:004010C7                 add     esp, 4
.text:004010CA                 call    loc_4010D3           ; Call the decrypted code
.text:004010CF                 mov     esp, ebp
.text:004010D1                 pop     ebp
.text:004010D2                 retn

I wrote a simple Python script that will decrypt the code for me in IDA:
Code decryptor, IDAPythonimport idc

codeStart = 0x004010D3
codeSize = 0x33
codeKey = 0xBEEFCABE

i = 0;
while(i < codeSize):
    PatchDword(codeStart+(i*4), (Dword(codeStart+(i*4)) ^ codeKey))
    i += 1

And the code is decrypted:
Decrypted code, IDA decompileint sub_4010D3() {
    v5 = 0xA6C6163;                                                              // Correct code second DWORD
    v6 = 0x6967616D;                                                             // Correct code first DWORD
    puts(aPleaseEnterThe);
    memset(v2, 0, 0x10u);
    v4 = 0;
    i = 0;
    do {                                                                         // Read the user's input
        --stru_407088._cnt;
        if (stru_407088._cnt < 0) {
          v1 = _filbuf(&stru_407088);
        } else {
          v1 = *stru_407088._ptr;
          ++stru_407088._ptr;
        }
        v8 = v1;
        v2[v4++] = v1;
    } while (v8 != 10 && v8 && v4 < 0x10);
    v7 = (int)v2;
    for (i = 0; i < 8; i += 4) {                                                 // The correct code is 8 bytes long
        if (*(_DWORD *)(v7 + 4 * (i >> 2)) != *(&v4 + ((v4 - i) >> 2))) {        // Compare a DWORD from the user
                                                                                 // with a DWORD from the correct code
            ((void (__cdecl *)(_DWORD, int))sub_40140E)(aInvalidPasswor, v1);    // Incorrect code message
            return 0;
        }
    }
    sub_40140E(aThePasswordIsS, v2);                                             // Correct code message
    return 0;
}

That looks pretty much the same way as in the previous challenge.
Converting the two parts of the correct code from DWORDs to ASCII gives us "magi" and "cal\x0A" or just "magical":


Yep, this is it.

Application Challenge #7 (Windows)


Target: app7win.exe, encrypted.enc
Requirement: Find the password
Difficulty: medium

This one is marked as medium difficulty, and it's again a console VC++ application:


The encrypted.enc file contains this:
encrypted.enc, HxDOffset    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

00000000  31 4D 39 35 33 45 61 44 65 16 54 56 16 54 56 15    1M953EaDe.TV.TV.
00000010  67 84 56 23 45 67 64 56 78 96 43 57 89 54 98 75    g„V#EgdVx–CW‰T.u
00000020  98 74 32 59 82 39 F9 8A D9 8F 42 98 F4 39 79 34    .t2Y‚9щЉЩЏB.ф9y4
00000030  8E F9 A8 DF 98 AD 7F 09 8D 98 43 F2 98 A7 F0 A8    ЋщЁЯ.­..Ќ.Cт.§рЁ
00000040  DD A9 F7 6D BA F9 7B 48 7A DF 7D A9 F8 69 8E A8    Э©чmєщ{HzЯ}©шiЋЁ
00000050  7A 6B 84 E6 F8 B7 68 74 A6 6A 48 7F A6 46 FA 9F    zk„жш·ht¦jH.¦Fъџ
00000060  86 48 7A 79 A8 E6 92 38 F7 F9 76 92 38 69 82 35    †HzyЁж’8чщv’8i‚5
00000070  87 E6 F7 AD 6F 98 7A 57 8F 68 27 35 92 38 75 82    ‡жч­o.zWЏh'5’8u‚
00000080  36 52 35 A8 7F 53 29 67 89 36 24 73 25 98 36 27    6R5Ё.S)g‰6$s%.6'
00000090  36 29 87 35 87 32 63 65 93 82 56 5A 87 3A 37 67    6)‡5‡2ce“‚VZ‡:7g
000000A0  3A 67 8A 58 72 63 87 65 32 78 56 A9 87 35 A6 98    :gЉXrc‡e2xV©‡5¦.
000000B0  A6 38 76 38 75 63 29 85 68 79 32 65 87 26 53 92    ¦8v8uc)…hy2e‡&S’
000000C0  85 63 28 95 6F 98 76 3A 97 86 9A 87 56 96 39 87    …c(•o.v:—†љ‡V–9‡
000000D0  5A 65 98 A3 76 59 A3 87 6A 59 87 69 87 5A 63 98    Ze.ЈvYЈ‡jY‡i‡Zc.
000000E0  76 FA 39 87 68 7A 56 87 FA 96 87 46 A8 96 98 47    vъ9‡hzV‡ъ–‡FЁ–.G
000000F0  6A 48 96 4A 9F 84 A7 F6 87 4A 55 E9 68 7D 6F A8    jH–Jџ„§ц‡JUйh}oЁ
00000100  97 A6 F9 69 84 7A 64 98 76 93 53 98 98 26 3F 89    —¦щi„zd.v“S..&?‰
00000110  73 26 F8 72 94 F8 79 87 24 82 8F 5A 08 7D F5 A8    s&шr”шy‡$‚ЏZ.}хЁ
00000120  43 53 29 F9 52 87 3E 59 F6 32 B9 6D 8A 9F AD 78    CS)щR‡>Yц2№mЉџ­x
00000130  FA 6F D0 9A F5 DA 9F AF 29 32 98 5F 49 59 F8 7D    ъoРљхЪџЇ)2._IYш}
00000140  A5 FA D8 F6 9A 9D F9 64 29 F6 39 D6 5F 87 A6 7E    ҐъШцљќщd)ц9Ц_‡¦~
00000150  78 D9 F6 98 E7 68 7D AF 67 9A 8D F8 A6 E6 FA 90    xЩц.зh}ЇgљЌш¦жъђ
00000160  86 F7 AD F7 F0 9A 06 E8 F4 A9 7F 49 A8 76 D7 FA    †ч­чрљ.иф©.IЁvЧъ
00000170  D9 F6 7D FA D8 76 FA 98 76 F9 A8 7D FA F6 98 4F    Щц}ъШvъ.vщЁ}ъц.O
00000180  66 34 FA DF A8 76 98 47 6F 84 79 A6 F8 7A DF AD    f4ъЯЁv.Go„y¦шzЯ­
00000190  FA 94 63 78 6F AD 57 6F A5 76 DF 5F DA FA FA 86    ъ”cxo­WoҐvЯ_Ъъъ†
000001A0  F8 7D 6A F8 72 FA 87 6D 87 F6 A8 76 F8 74 6F 78    ш}jшrъ‡m‡цЁvшtox
000001B0  8A 68 76 F4 68 7F A6 87 46 82 76 58 73 26 58 76    Љhvфh.¦‡F‚vXs&Xv
000001C0  87 FA 68 7D A6 F8 7A 68 74 68 76 36 48 76 A8 A7    ‡ъh}¦шzhthv6HvЁ§
000001D0  6A 87 46 87 F6 A8 76 F4 87 A6 FA 67 A9 46 28 66    j‡F‡цЁvф‡¦ъg©F(f

And the code:
Entry point, IDA decompileint __cdecl main(int argc, const char **argv, const char **envp) {
    puts(aPleaseEnterThe);                                                  // "Please enter the password:"
    memset(v10, 0, 0x10u);                                                  // v10 will hold the correct pass
                                                                            // and it's limited to 0x10 bytes
    v8 = 0;
    v9 = 0;
    v6 = 0;
    do {                                                                    // / read the user's password
        v11 = j___fgetchar();                                               // | sum the characters from the user's password
        v8 += v11;                                                          // | this will also add the ENTER key code - 0x0A
    } while (v11 != '\n' && v11);                                           // \
    v4 = fopen(aEncrypted_enc, aRb);                                        // "encrypted.enc"
    if (v4) {
        while (!(v6 & 4) || !(v6 & 1)) {                                    // Written like that, the loop limit is set to 5
            if (sub_401279(&v7, 1u, 1u, v4) != 1) {                         // this is just a fread() wrapper
                puts(aAnErrorOccured);                                      // "An error occurred"
                return 0;
            }
            v9 += v8 ^ (unsigned __int8)v7;                                 // take the user's password sum and XOR it
                                                                            // with a byte from the encrypted.enc file
                                                                            // that value should later match the 0xDCA from down below
            v10[v6] = v8 ^ v7;                                              // / this will decrypt the correct site code
            for (i = 0; i < v8; ++i) {                                      // | by using the user code's sum
                if (v10[v6] & 1) {                                          // |
                    v10[v6] = (signed int)(unsigned __int8)v10[v6] >> 1;    // |
                    v10[v6] |= 0x80u;                                       // |
                } else {                                                    // |
                    v10[v6] = (signed int)(unsigned __int8)v10[v6] >> 1;    // |
                }                                                           // |
            }                                                               // |
            v10[v6++] += 3;                                                 // \
        }
        fclose(v4);
        if (v9 == 0xDCA) {                                                  // this check will actually help me beat the challenge!
            printf(aCongratulation, v10);                                   // "Congratulations, The password is \'"
        } else {
            puts(aInvalidPasswor);                                          // "Invalid Password"
        }
        result = 0;
    } else {
        puts(aFailedToOpenEn);                                              // "Failed to open encrypted.enc"
        result = 0;
    }
    return result;
}

I can use few methods to defeat this challenge. First, let's see what information I have so far:
1. The user code is summed up, and later that sum is used for calculations. Therefore, the user code itself doesn't matter much, as long the its sum is the correct one;
2. The second loop, that reads the encrypred.enc file runs only 5 times, so only the first 5 bytes of encrypted.enc are used;
3. The second loop calculates the verification sum (v9), using a byte from the encrypted.enc XOR-ed with the sum of the user's code;
4. The second loop decrypts the site password (v10) using a byte from encrypted.enc XOR-ed with the sum of the user's code;
5. The final verification checks if the verification sum (v9) is equal to the hardcoded value of 0xDCA;

Having in mind the above, it's obvious that there's a certain user code sum that XOR-ed and added with the first 5 bytes of the encrypted.enc must result in the value of 0xDCA.
I don't care about the exact user's code right now, so I can write some code to determine the exact sum that will end as 0xDCA:
User code sum bruteforcer, Pythonencrypted_enc_data = "1M953" # encrypted.enc first 5 bytes
sum = i = 0

while(sum != 0xDCA):
    i += 1
    sum = 0
    for c in encrypted_enc_data:
        sum += ord(c) ^ i

print "Correct user sum is: %X" % i

Running this code gives me the value of 0x2F1, and that's the correct sum that the user's code should make when every character is added.
From here I can subtract 0x0A, because that's the value of the ENTER key character (new line) and I now got 0x2E7.
I can now try to build a working user code, by subtracting character values from that value of 0x2E7:
Manual building of a working code0x2E7 - 0x7A ('z') = 0x26D
0x26D - 0x7A ('z') = 0x1F3
0x1F3 - 0x7A ('z') = 0x179
0x179 - 0x7A ('z') = 0xFF
0xFF - 0x7A ('z') = 0x85
; if I subtract 0x7A again, I'll end up with  0x0B, and there's no printable character with the value of 0x0B
; so instead I'll subtract 0x42 ('B') and leave with 0x43 ('C')
0x85 - 0x42 ('B') = 0x43 ('C')

According to my logic, a possible correct code could be "zzzzzBC" so let's try it out:


Nice!
Since I knew the correct user code sum, I could completely skip the above by just writing a implementation of the site code decryption routine:
Site code decrypt, Pythonencrypted_enc_data = "1M953" # encrypted.enc first 5 bytes
sum = 0x2F1
i = 0
password = ""
for c in encrypted_enc_data:
    a = (ord(c) ^ sum) & 0xFF
    for i in range(sum):
        if (a & 1):
            a = a >> 1 | 0x80
        else:
            a = a >> 1
    password += chr(a+3)

print "Site's password is:", password

Finally, to make this solution complete, I'll write a random key generator:
User code keygen, Pythonimport random

charset = range(0x21, 0x7E) # I'll use all of the printable characters

sum = 0x2F1 - 0x0A # subtract the value of \n
code = ""
while sum > 0:
    c = charset[random.randint(0, len(charset))-1]
    if (sum/2 in charset):
        c = sum/2
        code += chr(c)
        code += chr(sum-c)
        break
    code += chr(c)
    sum -= c
print "Correct app password: \"%s\"" % code

Alright, application challenge #7 is completed!

Application Challenge #8 (Windows)


Target: app8win.exe
Requirement: Find the 6 digit code
Difficulty: medium

Written in VB6, this one looks interesting (to say the least):


The user is required to enter 6 digits by pressing the keys on the keypad. On the 7th key pressed, the app will either show the site password or just exit without warning.
Even watching the IDA's navigator we can clearly distinct the the code blocks (in brown) out of the rest data:


Going to the beginning of the code, I already see something familiar from the previous challenge written in VB6 - #4:
VB6 event table, IDA disassembly.text:00405ECC loc_405ECC:
.text:00405ECC                 sub     dword ptr [esp+4], 37h
.text:00405ED4                 jmp     loc_406040
.text:00405ED9 loc_405ED9:
.text:00405ED9                 sub     dword ptr [esp+4], 3Fh
.text:00405EE1                 jmp     loc_406100
.text:00405EE6 loc_405EE6:
.text:00405EE6                 sub     dword ptr [esp+4], 43h
.text:00405EEE                 jmp     loc_406250
.text:00405EF3 loc_405EF3:
.text:00405EF3                 sub     dword ptr [esp+4], 47h
.text:00405EFB                 jmp     loc_4063A0
.text:00405F00 loc_405F00:
.text:00405F00                 sub     dword ptr [esp+4], 4Bh
.text:00405F08                 jmp     loc_4064F0
.text:00405F0D loc_405F0D:
.text:00405F0D                 sub     dword ptr [esp+4], 4Fh
.text:00405F15                 jmp     loc_406640
.text:00405F1A loc_405F1A:
.text:00405F1A                 sub     dword ptr [esp+4], 53h
.text:00405F22                 jmp     loc_406790
.text:00405F27 loc_405F27:
.text:00405F27                 sub     dword ptr [esp+4], 57h
.text:00405F2F                 jmp     loc_4068E0
.text:00405F34 loc_405F34:
.text:00405F34                 sub     dword ptr [esp+4], 5Bh
.text:00405F3C                 jmp     loc_406A30
.text:00405F41 loc_405F41:
.text:00405F41                 sub     dword ptr [esp+4], 5Fh
.text:00405F49                 jmp     loc_406B80
.text:00405F4E loc_405F4E:
.text:00405F4E                 sub     dword ptr [esp+4], 3Bh
.text:00405F56                 jmp     loc_406CD0
.text:00405F5B loc_405F5B:
.text:00405F5B                 sub     dword ptr [esp+4], 63h
.text:00405F63                 jmp     loc_406D40

This obviously is the same event table that redirects the code flow according to user's interaction.

But let's assume this is cheating, and move to the debugger instead. I'll first get a list of the intermodular calls:
Intermodular calls, x86dbgAddress  Disassembly                                 Destination                  
00406D0F call dword ptr ds:[<&__vbaEnd>]             app8win.&__vbaEnd
0040772B call dword ptr ds:[<&__vbaEnd>]             app8win.&__vbaEnd
00407702 call dword ptr ds:[<&__vbaLenBstr>]         app8win.&__vbaLenBstr
00406AD2 call dword ptr ds:[<&__vbaStrCat>]          app8win.&__vbaStrCat
00406442 call dword ptr ds:[<&__vbaStrCat>]          app8win.&__vbaStrCat
00406982 call dword ptr ds:[<&__vbaStrCat>]          app8win.&__vbaStrCat
004066E2 call dword ptr ds:[<&__vbaStrCat>]          app8win.&__vbaStrCat
00406C22 call dword ptr ds:[<&__vbaStrCat>]          app8win.&__vbaStrCat
00406832 call dword ptr ds:[<&__vbaStrCat>]          app8win.&__vbaStrCat
004061A2 call dword ptr ds:[<&__vbaStrCat>]          app8win.&__vbaStrCat
004062F2 call dword ptr ds:[<&__vbaStrCat>]          app8win.&__vbaStrCat
00406592 call dword ptr ds:[<&__vbaStrCat>]          app8win.&__vbaStrCat
00406ADD call dword ptr ds:[<&__vbaStrMove>]         app8win.&__vbaStrMove
004062FD call dword ptr ds:[<&__vbaStrMove>]         app8win.&__vbaStrMove
004060A8 call dword ptr ds:[<&__vbaStrMove>]         app8win.&__vbaStrMove
0040659D call dword ptr ds:[<&__vbaStrMove>]         app8win.&__vbaStrMove
0040683D call dword ptr ds:[<&__vbaStrMove>]         app8win.&__vbaStrMove
00406C2D call dword ptr ds:[<&__vbaStrMove>]         app8win.&__vbaStrMove
0040698D call dword ptr ds:[<&__vbaStrMove>]         app8win.&__vbaStrMove
004061AD call dword ptr ds:[<&__vbaStrMove>]         app8win.&__vbaStrMove
004066ED call dword ptr ds:[<&__vbaStrMove>]         app8win.&__vbaStrMove
0040644D call dword ptr ds:[<&__vbaStrMove>]         app8win.&__vbaStrMove
00407470 call dword ptr ds:[<&__vbaVarDup>]          app8win.&__vbaVarDup
004070CF call dword ptr ds:[<&__vbaVarTstEq>]        app8win.&__vbaVarTstEq
004075A3 call dword ptr ds:[<&rtcMsgBox>]            app8win.&rtcMsgBox
0040609D call dword ptr ds:[<&rtcStrReverse>]        app8win.&rtcStrReverse
00401299 call <app8win.ThunRTMain>                   app8win.ThunRTMain
; for clarity I've removed calls to __vbaFreeObj, __vbaFreeObjList, __vbaFreeStr, __vbaFreeStrList, __vbaFreeVarList,
; __vbaHresultCheckObj and __vbaObjSet

From all these, __vbaVarTstEq looks pretty interesting so, I'll put a breakpoint on it, and press some of the app's keys:
__vbaVarTstEq call, x86dbg004070CB | 52                       | push edx
004070CC | FF D7                    | call edi                                ; edi:__vbaVarCat
004070CE | 50                       | push eax
004070CF | FF 15 4C 10 40 00        | call dword ptr ds:[<&__vbaVarTstEq>]    ; break here
004070D5 | 8D 4D E4                 | lea ecx,dword ptr ss:[ebp-1C]
004070D8 | 89 85 68 FB FF FF        | mov dword ptr ss:[ebp-498],eax
004070DE | FF 15 B4 10 40 00        | call dword ptr ds:[<&__vbaFreeObj>]

If that's comparing the correct key with the user's one, I should look upwards to see how the valid code is constructed.
I can also check what EAX is holding:
__vbaVarTstEq parameter, x86dbg0012F114  08 00 00 00 90 2A 1D 00 D4 55 1E 00 50 04 00 00  .....*..ÔU..P...  
0012F124  08 00 AB 01 E8 04 1E 00 0C 55 1E 00 27 CD 97 72  ..«.è....U..'Í.r  

In VB6, the call parameters are actually objects with their own structure, so I can't just dump the address EAX points and expect to get the actual thing - in this case the valid code.
Here, the correct code is contained within the third DWORD - D4 55 1E 00, or address 001E55D4.
But gain, let's assume this is cheating, and go upwards from __vbaVarTstEq's call and look around:
Code before __vbaVarTstEq, x86dbg00406F28 | 50                                 | push eax                                                    |
00406F29 | 6A 01                              | push 1                                                      |
00406F2B | 8D 55 C4                           | lea edx,dword ptr ss:[ebp-3C]                               |
00406F2E | 89 5D E8                           | mov dword ptr ss:[ebp-18],ebx                               | ebx:rtcMidCharVar
00406F31 | 8B 1D 40 10 40 00                  | mov ebx,dword ptr ds:[<&rtcMidCharVar>]                     |
00406F37 | 83 C6 34                           | add esi,34                                                  | esi:&L"987654321"
00406F3A | BF 08 40 00 00                     | mov edi,4008                                                |
00406F3F | 51                                 | push ecx                                                    |
00406F40 | 52                                 | push edx                                                    |
00406F41 | C7 85 C4 FE FF FF 08 80 00 00      | mov dword ptr ss:[ebp-13C],8008                             |
00406F4B | C7 45 DC 01 00 00 00               | mov dword ptr ss:[ebp-24],1                                 |
00406F52 | C7 45 D4 02 00 00 00               | mov dword ptr ss:[ebp-2C],2                                 |
00406F59 | 89 B5 4C FD FF FF                  | mov dword ptr ss:[ebp-2B4],esi                              | [ebp-2B4]:&L"987654321"
00406F5F | 89 BD 44 FD FF FF                  | mov dword ptr ss:[ebp-2BC],edi                              | edi:__vbaVarCat
00406F65 | FF D3                              | call ebx                                                    | ebx:rtcMidCharVar
00406F67 | 8D 45 B4                           | lea eax,dword ptr ss:[ebp-4C]                               |
00406F6A | 8D 8D 24 FD FF FF                  | lea ecx,dword ptr ss:[ebp-2DC]                              |
00406F70 | 50                                 | push eax                                                    |
00406F71 | 6A 08                              | push 8                                                      |
00406F73 | 8D 55 A4                           | lea edx,dword ptr ss:[ebp-5C]                               |
00406F76 | 51                                 | push ecx                                                    |
00406F77 | 52                                 | push edx                                                    |
00406F78 | C7 45 BC 01 00 00 00               | mov dword ptr ss:[ebp-44],1                                 |
00406F7F | C7 45 B4 02 00 00 00               | mov dword ptr ss:[ebp-4C],2                                 |
00406F86 | 89 B5 2C FD FF FF                  | mov dword ptr ss:[ebp-2D4],esi                              | [ebp-2D4]:&L"987654321"
00406F8C | 89 BD 24 FD FF FF                  | mov dword ptr ss:[ebp-2DC],edi                              | edi:__vbaVarCat
00406F92 | FF D3                              | call ebx                                                    | ebx:rtcMidCharVar
00406F94 | 8D 45 84                           | lea eax,dword ptr ss:[ebp-7C]                               |
00406F97 | 8D 8D 04 FD FF FF                  | lea ecx,dword ptr ss:[ebp-2FC]                              |
00406F9D | 50                                 | push eax                                                    |
00406F9E | 6A 05                              | push 5                                                      |
00406FA0 | 8D 95 74 FF FF FF                  | lea edx,dword ptr ss:[ebp-8C]                               |
00406FA6 | 51                                 | push ecx                                                    |
00406FA7 | 52                                 | push edx                                                    |
00406FA8 | C7 45 8C 01 00 00 00               | mov dword ptr ss:[ebp-74],1                                 |
00406FAF | C7 45 84 02 00 00 00               | mov dword ptr ss:[ebp-7C],2                                 |
00406FB6 | 89 B5 0C FD FF FF                  | mov dword ptr ss:[ebp-2F4],esi                              | [ebp-2F4]:&L"987654321"
00406FBC | 89 BD 04 FD FF FF                  | mov dword ptr ss:[ebp-2FC],edi                              | edi:__vbaVarCat
00406FC2 | FF D3                              | call ebx                                                    | ebx:rtcMidCharVar
00406FC4 | 8D 85 54 FF FF FF                  | lea eax,dword ptr ss:[ebp-AC]                               |
00406FCA | 8D 8D E4 FC FF FF                  | lea ecx,dword ptr ss:[ebp-31C]                              |
00406FD0 | 50                                 | push eax                                                    |
00406FD1 | 6A 08                              | push 8                                                      |
00406FD3 | 8D 95 44 FF FF FF                  | lea edx,dword ptr ss:[ebp-BC]                               |
00406FD9 | 51                                 | push ecx                                                    |
00406FDA | 52                                 | push edx                                                    |
00406FDB | C7 85 5C FF FF FF 01 00 00 00      | mov dword ptr ss:[ebp-A4],1                                 |
00406FE5 | C7 85 54 FF FF FF 02 00 00 00      | mov dword ptr ss:[ebp-AC],2                                 |
00406FEF | 89 B5 EC FC FF FF                  | mov dword ptr ss:[ebp-314],esi                              | [ebp-314]:&L"987654321"
00406FF5 | 89 BD E4 FC FF FF                  | mov dword ptr ss:[ebp-31C],edi                              | edi:__vbaVarCat
00406FFB | FF D3                              | call ebx                                                    | ebx:rtcMidCharVar
00406FFD | 8D 85 24 FF FF FF                  | lea eax,dword ptr ss:[ebp-DC]                               |
00407003 | 8D 8D C4 FC FF FF                  | lea ecx,dword ptr ss:[ebp-33C]                              |
00407009 | 50                                 | push eax                                                    |
0040700A | 6A 06                              | push 6                                                      |
0040700C | 8D 95 14 FF FF FF                  | lea edx,dword ptr ss:[ebp-EC]                               |
00407012 | 51                                 | push ecx                                                    |
00407013 | 52                                 | push edx                                                    |
00407014 | C7 85 2C FF FF FF 01 00 00 00      | mov dword ptr ss:[ebp-D4],1                                 |
0040701E | C7 85 24 FF FF FF 02 00 00 00      | mov dword ptr ss:[ebp-DC],2                                 |
00407028 | 89 B5 CC FC FF FF                  | mov dword ptr ss:[ebp-334],esi                              | [ebp-334]:&L"987654321"
0040702E | 89 BD C4 FC FF FF                  | mov dword ptr ss:[ebp-33C],edi                              | edi:__vbaVarCat
00407034 | FF D3                              | call ebx                                                    | ebx:rtcMidCharVar
00407036 | 8D 85 F4 FE FF FF                  | lea eax,dword ptr ss:[ebp-10C]                              |
0040703C | 8D 8D A4 FC FF FF                  | lea ecx,dword ptr ss:[ebp-35C]                              |
00407042 | 50                                 | push eax                                                    |
00407043 | 6A 02                              | push 2                                                      |
00407045 | 8D 95 E4 FE FF FF                  | lea edx,dword ptr ss:[ebp-11C]                              |
0040704B | 51                                 | push ecx                                                    |
0040704C | 52                                 | push edx                                                    |
0040704D | C7 85 FC FE FF FF 01 00 00 00      | mov dword ptr ss:[ebp-104],1                                |
00407057 | C7 85 F4 FE FF FF 02 00 00 00      | mov dword ptr ss:[ebp-10C],2                                |
00407061 | 89 B5 AC FC FF FF                  | mov dword ptr ss:[ebp-354],esi                              | [ebp-354]:&L"987654321"
00407067 | 89 BD A4 FC FF FF                  | mov dword ptr ss:[ebp-35C],edi                              | edi:__vbaVarCat
0040706D | FF D3                              | call ebx                                                    | ebx:rtcMidCharVar

Ok, that looks promising and the fact that x86dbg resolved the string "987654321" makes it pretty obvious too.
rtcMidCharVar is actually the API name of Visual Basic's in-language function Mid().
Using MSDN, we can see the Mid() function is used to retrieve a part of a string, pretty much, like for example, JavaScript's substr() works.
Watching the PUSH instructions I can clearly see the third parameter is always an integer between 0 and 9 as follows:
indexes1, 8, 5, 8, 6, 2

I already know the correct code is 6 digits long, because that's in the challenge description, so it seems I'm on the right track.
Now, because Mid() is used, those values should be indexes of a pre-existing string, and since x86dbg was so kind to resolve it, I know it's the string "987654321".
There's something I should mention here. Usually indexes in arrays, strings, etc. start from 0, but this one actually starts from 1.
So, the index of 1 actually points to '9' instead of pointing to '8'.

Having that in mind, after applying the indexes from above to that string gives me the code "925248":


Alright, my code is correct, and I have the site's password.
Speaking of which, where is the site's password created?
The answer lies beneath the __vbaVarTstEq CALL:
Site password contruction, x86asm00407173 | 6A 08                              | push 8                                                      |
00407175 | 8D 55 C4                           | lea edx,dword ptr ss:[ebp-3C]                               |
00407178 | 51                                 | push ecx                                                    |
00407179 | 52                                 | push edx                                                    |
0040717A | C7 45 DC 01 00 00 00               | mov dword ptr ss:[ebp-24],1                                 |
00407181 | C7 45 D4 02 00 00 00               | mov dword ptr ss:[ebp-2C],2                                 |
00407188 | 89 B5 4C FD FF FF                  | mov dword ptr ss:[ebp-2B4],esi                              | [ebp-2B4]:&L"987654321"
0040718E | C7 85 44 FD FF FF 08 40 00 00      | mov dword ptr ss:[ebp-2BC],4008                             |
00407198 | FF D3                              | call ebx                                                    | ebx:rtcMidCharVar
0040719A | 8D 45 A4                           | lea eax,dword ptr ss:[ebp-5C]                               |
0040719D | 8D 8D 14 FD FF FF                  | lea ecx,dword ptr ss:[ebp-2EC]                              |
004071A3 | 50                                 | push eax                                                    |
004071A4 | 6A 04                              | push 4                                                      |
004071A6 | 8D 55 94                           | lea edx,dword ptr ss:[ebp-6C]                               |
004071A9 | 51                                 | push ecx                                                    |
004071AA | 52                                 | push edx                                                    |
004071AB | C7 45 AC 01 00 00 00               | mov dword ptr ss:[ebp-54],1                                 |
004071B2 | C7 45 A4 02 00 00 00               | mov dword ptr ss:[ebp-5C],2                                 |
004071B9 | 89 B5 1C FD FF FF                  | mov dword ptr ss:[ebp-2E4],esi                              |
004071BF | C7 85 14 FD FF FF 08 40 00 00      | mov dword ptr ss:[ebp-2EC],4008                             |
004071C9 | FF D3                              | call ebx                                                    | ebx:rtcMidCharVar
004071CB | 8D 85 74 FF FF FF                  | lea eax,dword ptr ss:[ebp-8C]                               |
004071D1 | 8D 8D F4 FC FF FF                  | lea ecx,dword ptr ss:[ebp-30C]                              |
004071D7 | 50                                 | push eax                                                    |
004071D8 | 6A 06                              | push 6                                                      |
004071DA | 8D 95 64 FF FF FF                  | lea edx,dword ptr ss:[ebp-9C]                               |
004071E0 | 51                                 | push ecx                                                    |
004071E1 | 52                                 | push edx                                                    |
004071E2 | C7 85 7C FF FF FF 01 00 00 00      | mov dword ptr ss:[ebp-84],1                                 | [ebp-84]:"$hjw"
004071EC | C7 85 74 FF FF FF 02 00 00 00      | mov dword ptr ss:[ebp-8C],2                                 |
004071F6 | 89 B5 FC FC FF FF                  | mov dword ptr ss:[ebp-304],esi                              |
004071FC | C7 85 F4 FC FF FF 08 40 00 00      | mov dword ptr ss:[ebp-30C],4008                             |
00407206 | FF D3                              | call ebx                                                    | ebx:rtcMidCharVar
00407208 | 8D 85 44 FF FF FF                  | lea eax,dword ptr ss:[ebp-BC]                               |
0040720E | 8D 8D D4 FC FF FF                  | lea ecx,dword ptr ss:[ebp-32C]                              |
; continues

So, indexes 8, 4 and 6, pointing to '2', '6', '4' and so on.

And that's all about challenge #8

Application Challenge #9 (Windows)


Target: app9win.exe
Requirement: Match the beeps to the 'Play' button
Difficulty: medium

Yet another odd looking challenge written in VB6:


With the experience from the previous VB6 challenges, I can actually waltz through this one pretty easy.
Thanks to IDA's navigator, I'll locate the event table, set breakpoints and determine what's what:
Event table, IDA disassembly.text:00404F40 loc_404F40:
.text:00404F40                 sub     dword ptr [esp+4], 53h    ; Main window create
.text:00404F48                 jmp     loc_4054C0
.text:00404F4D loc_404F4D:
.text:00404F4D                 sub     dword ptr [esp+4], 4Bh    ; "Play" button pressed
.text:00404F55                 jmp     loc_405570
.text:00404F5A loc_404F5A:
.text:00404F5A                 sub     dword ptr [esp+4], 3Fh    ; "Match1" button pressed
.text:00404F62                 jmp     loc_405610
.text:00404F67 loc_404F67:
.text:00404F67                 sub     dword ptr [esp+4], 43h    ; "Match2" button pressed
.text:00404F6F                 jmp     loc_405690
.text:00404F74 loc_404F74:
.text:00404F74                 sub     dword ptr [esp+4], 47h    ; "Match3" button pressed
.text:00404F7C                 jmp     loc_405710
.text:00404F81 loc_404F81:
.text:00404F81                 sub     dword ptr [esp+4], 4Fh    ; mystery action, that is constantly running in loop
.text:00404F89                 jmp     loc_405790

If I want I can redirect some of the button's actions to that mystery action down there, but that wont show me the correct password.

First, let's see what the "Play" button does, and how these sounds are generated:
Play button action, IDA disassembly.text:00405570 loc_405570:
.text:00405570                 push    ebp
.text:00405571                 mov     ebp, esp
.text:00405573                 sub     esp, 0Ch
.text:00405576                 push    offset loc_4010F6
.text:0040557B                 mov     eax, large fs:0
.text:00405581                 push    eax
.text:00405582                 mov     large fs:0, esp
.text:00405589                 sub     esp, 8
.text:0040558C                 push    ebx
.text:0040558D                 push    esi
.text:0040558E                 push    edi
.text:0040558F                 mov     [ebp-0Ch], esp
.text:00405592                 mov     dword ptr [ebp-8], offset dword_4010C0
.text:00405599                 mov     eax, [ebp+8]
.text:0040559C                 mov     ecx, eax
.text:0040559E                 and     ecx, 1
.text:004055A1                 mov     [ebp-4], ecx
.text:004055A4                 and     al, 0FEh
.text:004055A6                 push    eax
.text:004055A7                 mov     [ebp+8], eax
.text:004055AA                 mov     edx, [eax]
.text:004055AC                 call    dword ptr [edx+4]
.text:004055AF                 push    12Ch                            ;/ First sound
.text:004055B4                 push    64h                             ;|
.text:004055B6                 call    sub_40519C                      ;\ DllFunctionCall(kernel32.Beep)
.text:004055BB                 mov     esi, ds:__vbaSetSystemError
.text:004055C1                 call    esi ; __vbaSetSystemError
.text:004055C3                 push    12Ch                            ;/ Second sound
.text:004055C8                 push    1F4h                            ;|
.text:004055CD                 call    sub_40519C                      ;\ DllFunctionCall(kernel32.Beep)
.text:004055D2                 call    esi ; __vbaSetSystemError
.text:004055D4                 push    12Ch                            ;/ Third sound
.text:004055D9                 push    3E8h                            ;|
.text:004055DE                 call    sub_40519C                      ;\ DllFunctionCall(kernel32.Beep)
;trimmed

So, the sounds are generated using the Beep function. From MSDN we can see Beep takes two parameters:
BeepBOOL WINAPI Beep(
  _In_ DWORD dwFreq,
  _In_ DWORD dwDuration
);

The dwDuration is set to 0x012C for all three of them, and only the dwFreq is different.
Now let's see the "Match1" button code:
Match1 action.text:00405610                 push    ebp
.text:00405611                 mov     ebp, esp
.text:00405613                 sub     esp, 0Ch
.text:00405616                 push    offset loc_4010F6
.text:0040561B                 mov     eax, large fs:0
.text:00405621                 push    eax
.text:00405622                 mov     large fs:0, esp
.text:00405629                 sub     esp, 8
.text:0040562C                 push    ebx
.text:0040562D                 push    esi
.text:0040562E                 push    edi
.text:0040562F                 mov     [ebp-0Ch], esp
.text:00405632                 mov     dword ptr [ebp-8], offset dword_4010C8
.text:00405639                 mov     esi, [ebp+8]
.text:0040563C                 mov     eax, esi
.text:0040563E                 and     eax, 1
.text:00405641                 mov     [ebp-4], eax
.text:00405644                 and     esi, 0FFFFFFFEh
.text:00405647                 push    esi
.text:00405648                 mov     [ebp+8], esi
.text:0040564B                 mov     ecx, [esi]
.text:0040564D                 call    dword ptr [ecx+4]
.text:00405650                 mov     edx, [esi+34h]    ; where's this coming from?
.text:00405653                 push    12Ch              ;/ dwDuration
.text:00405658                 push    edx               ;| dwFreq
.text:00405659                 call    sub_40519C        ;\ DllFunctionCall(kernel32.Beep)
;trimmed

; edx=C8
; dword ptr[esi+34]=[0060051C]=C8


The dwDuration is again 0x012C, but the dwFreq here comes from a dynamic buffer instead from a hardcoded value and it's set to 0xC8.
Time to check that Main window initialization procedure and see where that 0xC8 came from:
Main window create procedure, IDA disassemble.text:004054C0                 push    ebp
.text:004054C1                 mov     ebp, esp
.text:004054C3                 sub     esp, 0Ch
.text:004054C6                 push    offset loc_4010F6
.text:004054CB                 mov     eax, large fs:0
.text:004054D1                 push    eax
.text:004054D2                 mov     large fs:0, esp
.text:004054D9                 sub     esp, 0Ch
.text:004054DC                 push    ebx
.text:004054DD                 push    esi
.text:004054DE                 push    edi
.text:004054DF                 mov     [ebp-0Ch], esp
.text:004054E2                 mov     dword ptr [ebp-8], offset dword_4010B0
.text:004054E9                 mov     esi, [ebp+8]
.text:004054EC                 mov     eax, esi
.text:004054EE                 and     eax, 1
.text:004054F1                 mov     [ebp-4], eax
.text:004054F4                 and     esi, 0FFFFFFFEh
.text:004054F7                 push    esi
.text:004054F8                 mov     [ebp+8], esi
.text:004054FB                 mov     ecx, [esi]
.text:004054FD                 call    dword ptr [ecx+4]
.text:00405500                 xor     ebx, ebx
.text:00405502                 mov     edx, offset aHtsApplication ; "HTS Application Challenge Programmed by"...
.text:00405507                 lea     ecx, [ebp-18h]
.text:0040550A                 mov     [ebp-18h], ebx
.text:0040550D                 call    ds:__vbaStrCopy
.text:00405513                 mov     edi, ds:__vbaI4Str
.text:00405519                 push    offset a200     ;/ Parameter = "200"
.text:0040551E                 call    edi             ;\ __vbaI4Str (convert string to integer)
.text:00405520                 push    offset a600     ;"600"
.text:00405525                 mov     [esi+34h], eax  ; result is stored here!
.text:00405528                 call    edi ; __vbaI4Str
.text:0040552A                 push    offset a1100    ; "1100"
.text:0040552F                 mov     [esi+38h], eax
.text:00405532                 call    edi ; __vbaI4Str
.text:00405534                 mov     [esi+3Ch], eax
.text:00405537                 mov     [ebp-4], ebx
.text:0040553A                 push    offset loc_405549
.text:0040553F                 lea     ecx, [ebp-18h]
.text:00405542                 call    ds:__vbaFreeStr
.text:00405548                 retn

Got it! That string to integer thing actually stores the dwFreq values for the three buttons.
I checked the three buttons and they are playing sounds with dwFreq equal to 0x64 (Match1), 0x1F4 (Match2) and 0x3E8 (Match3), but the values here are 200 (0xC8), 600 (0x258) and 1100 (0x44C).
What I did here was to change these strings to 100, 500 and 1000, let the program run and BAM!:


It's interesting to mention that pressing the Play, Match1, Match2 or Match3 buttons does nothing, and the only way to solve this challenge is to patch it like I did.

The correct password is constructed pretty much like it was done in the previous VB6 challenges:
Site code construction, IDA disassembly.text:00405B9A                 push    0Fh                                  ; first string index
.text:00405B9C                 lea     edx, [ebp-48h]
.text:00405B9F                 mov     ebx, 2
.text:00405BA4                 mov     esi, 4008h
.text:00405BA9                 push    ecx
.text:00405BAA                 push    edx
.text:00405BAB                 mov     dword ptr [ebp-240h], offset dword_4052C8
.text:00405BB5                 mov     dword ptr [ebp-248h], 8
.text:00405BBF                 mov     dword ptr [ebp-30h], 1
.text:00405BC6                 mov     [ebp-38h], ebx
.text:00405BC9                 mov     [ebp-228h], esi
.text:00405BCF                 call    edi ; rtcMidCharVar                  ; get character based on it's index in the charset string
.text:00405BD1                 lea     eax, [ebp-18h]
.text:00405BD4                 lea     ecx, [ebp-68h]
.text:00405BD7                 mov     [ebp-250h], eax
.text:00405BDD                 push    ecx
.text:00405BDE                 lea     edx, [ebp-258h]
.text:00405BE4                 push    12h                                  ; second string index
.text:00405BE6                 lea     eax, [ebp-78h]
.text:00405BE9                 push    edx
.text:00405BEA                 push    eax
.text:00405BEB                 mov     dword ptr [ebp-60h], 1
.text:00405BF2                 mov     [ebp-68h], ebx
.text:00405BF5                 mov     [ebp-258h], esi
.text:00405BFB                 call    edi ; rtcMidCharVar                  ; get character based on it's index in the charset string
; trimmed