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