Attack and Defense World REVERSE Novice Area/csaw2013reversing2

Static Debugging Method

Look at the title description, it says you can get flag by running it, download it and run it, it doesn't seem possible

First check if there is a shell. This is not, and it's a 32-bit program

Open with IDA32 bit, f5 view pseudocode

The next step is to analyze the code

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  int v3; // ecx
  CHAR *lpMem; // [esp+8h] [ebp-Ch]
  HANDLE hHeap; // [esp+10h] [ebp-4h]

  hHeap = HeapCreate(0x40000u, 0, 0);
  lpMem = (CHAR *)HeapAlloc(hHeap, 8u, MaxCount + 1);
  memcpy_s(lpMem, MaxCount, &unk_409B10, MaxCount);
  if ( sub_40102A() || IsDebuggerPresent() )
  {
    __debugbreak();
    sub_401000(v3 + 4, (int)lpMem);
    ExitProcess(0xFFFFFFFF);
  }
  MessageBoxA(0, lpMem + 1, "Flag", 2u);
  HeapFree(hHeap, 0, lpMem);
  HeapDestroy(hHeap);
  ExitProcess(0);
}

First check what HeapCreate() and HeapAlloc() do

These two statements are requesting a space of size Maxcount = 24h

Then copy the function memcpy_through a string () will &unk_ Copy the contents of 409B10 into lpMem


Next comes the if statement

if ( sub_40102A() || IsDebuggerPresent() )
  {
    __debugbreak();
    sub_401000(v3 + 4, (int)lpMem);
    ExitProcess(0xFFFFFFFF);
  }

Sub_ The 40102A() function returns directly 0, so it doesn't need to

IsDebuggerPresent() is a function that detects whether a program is being debugged. If it is detected that it is being debugged, it will exit directly. I also tried

This reverses the loneliness of debugging


Then skip the sentence immediately after

MessageBoxA(0, lpMem + 1, "Flag", 2u);


This is an output statement, combined with the previous pop-up window, the launch flag is inside plMem

Write a script to output content

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
    int lpMem[37] = {0x0BB,0x0CC,0x0A0,0x0BC,0x0DC,0x0D1,0x0BE,0x0B8,0x0CD,0x0CF,
     0x0BE,0x0AE,0x0D2,0x0C4,0x0AB,0x82,0x0D2,0x0D9,0x93,0x0B3,0x0D4,0xDE,
     0x93,0x0A9,0x0D3,0x0CB,0x0B8,0x82,0x0D3,0x0CB,0x0BE,0x0B9,0x9A,0x0D7,
     0x0CC,0x0DD};
    for(int i = 0 ; i < 36; i++)
    {
       printf("%c",lpMem[i]);
    }
    return 0;

}

Running out is garbage (garbage)

The only thing you haven't seen yet is what was in the previous if statement

There is a sub_inside 401000 function uses lpMem as a parameter, follow up to see

if ( sub_40102A() || IsDebuggerPresent() )
  {
    __debugbreak();
    sub_401000(v3 + 4, (int)lpMem);
    ExitProcess(0xFFFFFFFF);
  }

v2=dword_409B38

Then look at this loop, the value of the previous result can be ignored, and it will not exceed the length of this string by 36

And then naive I thought this was v2 every four exclusive or once, and the result was garbled or not

Then I found that converting this type to four numbers.


That loop should be a number in XOR v2, from which you can write a script

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
    int lpMem[37] = {0x0BB,0x0CC,0x0A0,0x0BC,0x0DC,0x0D1,0x0BE,0x0B8,0x0CD,0x0CF,
     0x0BE,0x0AE,0x0D2,0x0C4,0x0AB,0x82,0x0D2,0x0D9,0x93,0x0B3,0x0D4,0xDE,
     0x93,0x0A9,0x0D3,0x0CB,0x0B8,0x82,0x0D3,0x0CB,0x0BE,0x0B9,0x9A,0x0D7,
     0x0CC,0x0DD};
     int v2[4] = {0xBB,0XAA,0XCC,0XDD};
    for(int i = 0 ; i < 36; i++)
    {
       printf("%c",lpMem[i] ^ v2[ i  % 4]);
    }
    return 0;

}

Run to get results

Dynamic Debugging Method

Open with OLLYDDEBUG

Press F8 and keep running until you see this function, which is a debugging function. This is the judgment in the if statement.

if ( sub_40102A() || IsDebuggerPresent() )
  {
    __debugbreak();
    sub_401000(v3 + 4, (int)lpMem);
    ExitProcess(0xFFFFFFFF);
  }

You can see that there is a jnz statement on top of the call to this statement, and the jump has not yet been implemented. This should be || in the if statement, because the previous return is 0, so continue to determine the value to the right of ||

Looking down, here's a big jump that stops the program immediately after it's done, so double-click twice to change this command to jnz

There is also an int3 command, which causes an interrupt, so change this to NOP (meaning do nothing).


Changed instructions

Continue to press F8, see a jmp command, jump directly to the end program, this corresponds to debugbreak(), so continue to change it to nop

   __debugbreak();
    sub_401000(v3 + 4, (int)lpMem);
    ExitProcess(0xFFFFFFFF);

Continue to look down and there's another jmp directive, which corresponds to ExitProcess (0xFFFFFF), and change it to nop as well

   __debugbreak();
    sub_401000(v3 + 4, (int)lpMem);
    ExitProcess(0xFFFFFFFF);

I don't know what to do when the instructions are changed and it will automatically become two NOPs

Then press F8 to continue running. When you run here, a blank box pops up. Just click a button and continue running.

Continue running, flag is out


Added by himani on Tue, 18 Jan 2022 09:33:12 +0200