crackme0x00

(1) 查找字符串

IOLI-crackme程序下载

以下通过ODbgScript来找到密码和修改程序。

;修改strcmp的返回值eax
var start
var addr_pass
var pass
var strcmp

;reset = control+f2
;clear
lclr
gmi eip,entry
mov start,$RESULT
eval "entry = {start}"
log $RESULT
;rax2 -S "Password OK"      50617373776f7264204f4b
findmem #50617373776f7264204f4b#,start
;log $RESULT		00404041

sub $RESULT,1a
mov addr_pass,$RESULT
;00404027	250382
gstr addr_pass
mov pass,$RESULT
log pass
;push addr_pass
;pop addr_pass
;findcmd start,"test eax,eax"
;00401373 >|.  E8 98190000   call        00402D20	strcmp
findop start,#E898190000#
mov strcmp,$RESULT
eval "strcmp = {$RESULT}"
log $RESULT
bp strcmp
esto
sto
log eip
log eax
mov eax,0
esto
;run
ret
;修改je
var start
var strcmp
var jump
var tmp

lclr
gmi eip,entry
mov start,$RESULT
eval "entry = {start}"
log $RESULT

;00401373 >|.  E8 98190000   call        00402D20	strcmp
findop start,#E898190000#
mov strcmp,$RESULT
bp strcmp
mov jump,strcmp
add jump,7
log jump
;0040137A /74 0E /je short 0040138A		/jmp 0040138A /EB 0E
repl jump,#740E#,#EB0E#,2
(2) msvcrt.strcmp

调用strcmp

00401368  |.  C74424 04 274>mov     dword ptr [esp+4], 00404027      ; ||ASCII "250382"
00401370  |.  890424        mov     dword ptr [esp], eax             ; ||
00401373 >|.  E8 98190000   call                 ; |\strcmp
00401378  |.  85C0          test    eax, eax                         ; |
0040137A      74 0E         je      short 0040138A

;strcmp
77089B40 >  8B5424 04       mov     edx, dword ptr [esp+4]
77089B44    8B4C24 08       mov     ecx, dword ptr [esp+8]
77089B48    F7C2 03000000   test    edx, 3
...
77089B82    C3              retn

调用strcmp前的参数来源(按[esp]地址大小) strcmp(eax,pstr)

调用strcmp前时的参数来源 strcmp(edx,ecx)

调用strcmp返回值 eax = ffffffff(-1),0,1

(3) strcmp源码跟踪

调试源码 : microsoft doc

// crt_strcmp.c

#include 
#include 
#include 

char string1[] = "The quick brown dog jumps over the lazy fox";
char string2[] = "The QUICK brown dog jumps over the lazy fox";

int main( void )
{
   char tmp[20];
   int result;

   // Case sensitive
   printf( "Compare strings:\n   %s\n   %s\n\n", string1, string2 );
   result = strcmp( string1, string2 );
   if( result > 0 )
      strcpy_s( tmp, _countof(tmp), "greater than" );
   else if( result < 0 )
      strcpy_s( tmp, _countof (tmp), "less than" );
   else
      strcpy_s( tmp, _countof (tmp), "equal to" );
   printf( "   strcmp:   String 1 is %s string 2\n", tmp );

   // Case insensitive (could use equivalent _stricmp)
   result = _stricmp( string1, string2 );
   if( result > 0 )
      strcpy_s( tmp, _countof (tmp), "greater than" );
   else if( result < 0 )
      strcpy_s( tmp, _countof (tmp), "less than" );
   else
      strcpy_s( tmp, _countof (tmp), "equal to" );
   printf( "   _stricmp:  String 1 is %s string 2\n", tmp );
}

环境:Visual Studio,安装必选项:C++ 桌面应用程序开发 Windows Sdk
设置断点后调试,在调试\窗口\寄存器打开寄存器窗口,先逐步跟踪,再看源码所在的文件,最后打开反汇编窗口来调试。记录调用的堆栈如下:

main.cpp
	printf
	//stdio.h
		__crt_va_start(_ArgList, _Format);
			//VC/include/vardefs.h
			void __vcrt_va_start_verify_argument_type() throw()
		_Result = _vfprintf_l(stdout, _Format, NULL, _ArgList);
			return __stdio_common_vfprintf(_CRT_INTERNAL_LOCAL_PRINTF_OPTIONS, _Stream, _Format, _Locale, _ArgList);
			//windows kit/10/include/VRESION/ucrt/correct_stdio_config.h
			__declspec(noinline) __inline unsigned __int64* __CRTDECL __local_stdio_printf_options(void)
			{
				static unsigned __int64 _OptionsStorage;
				return &_OptionsStorage;
			}
		__crt_va_end(_ArgList);
		return _Result;
	result = strcmp(string1, string2);
		
			
    static int __cdecl invoke_main() throw()
    {
        return main(__argc, __argv, _get_initial_narrow_environment());
    }
	//vcruntime/exe_common.inl
	int const main_result = invoke_main();
	if (!__scrt_is_managed_app())
            exit(main_result);
	//vcruntime/utility_desktop.cpp
	extern "C" bool __cdecl __scrt_is_managed_app()
	{
		PIMAGE_DOS_HEADER const dos_header = reinterpret_cast<PIMAGE_DOS_HEADER>(GetModuleHandleW(nullptr));
		if (dos_header == nullptr)
			return false;
		...
		PIMAGE_NT_HEADERS const pe_header = reinterpret_cast<PIMAGE_NT_HEADERS>(
        reinterpret_cast<BYTE*>(dos_header) + dos_header->e_lfanew);
		
		if (pe_header->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
        return false;
	static __declspec(noinline) int __cdecl __scrt_common_main_seh() throw()
		if (!__scrt_is_managed_app())
				exit(main_result);

可以看出:在退出程序之前会通过__scrt_is_managed_app()来检查PE结构PIMAGE_NT_HEADERS的相关结构可以直接使用,这就是有时候写文件补丁时,会写的比较简洁的原因了。而如果对msvc的源码不够了解,就把握不了相关的结构和类型了,最好是自己动手写相关的结构和字段。

对比源码调试和反汇编调试:
源码调试时过程会相对简洁,但相关的定义很多,不知道具体是调用哪个dll里的函数。
反汇编调试过程多,通过内存映射,可以找到相应的dll,不会有那么多的定义,靠寄存器和内存的环境来反映。

(4) 查找输出输入(printf,scanf)执行的前一条指令

查找

调整程序窗口,同时查看程序的输出和OllyDBG的堆栈,一直按F7,直到出现输出,alt+m打开内存映射,可定位到ntdll

在OD中打开crackme0x00,定位到ntdll代码区。
相关函数调用:ntdll.ZwDeviceIoControlFile KERNELBA ntdll.ZwWriteFile

输出

output
77191DC0 >  B8 07001B00     mov     eax, 1B0007
77191DC5    BA 308D1A77     mov     edx, 771A8D30
77191DCA    FFD2            call    edx
77191DCC    C2 2800         retn    28
77191DCF    90              nop

输入

77191DD0 >  B8 08001A00     mov     eax, 1A0008                      ; UNICODE "00"
77191DD5    BA 308D1A77     mov     edx, 771A8D30
77191DDA    FFD2            call    edx
77191DDC    C2 2400         retn    24
77191DDF    90              nop

结束

end
77192030 >  B8 2C000700     mov     eax, 7002C
77192035    BA 308D1A77     mov     edx, 771A8D30
7719203A    FFD2            call    edx
7719203C    C2 0800         retn    8
7719203F    90              nop

重启时ntdll装入地址发生了变化,用ODbgScript来查找代码并设置断点

;ntdll
;循环查找opcode
ntdll:
	var start
	var end
	lclr
	gma "ntdll", codebase
	mov start,$RESULT
	log start
	
	gma "ntdll", codesize
	mov end,$RESULT
	add end,start
	sub end,2
	log end

lclr
compare:
	;output : B8 07001B00     mov     eax, 1B0007	
	;findcmd start,"mov edi,edx"
	findop start,#B807001B00#
	cmp $RESULT,0
	jne find
	je finished
find:
	log $RESULT
	bp $RESULT
	;bc $RESULT
	wrta "s.txt",$RESULT
	add $RESULT,1
	cmp end,$RESULT
	je finished
	jne add:
add:
	mov start,$RESULT
	jmp compare
finished:
	ret

你可能感兴趣的:(Binary)