小菜鸟一枚 发表于 2020-2-12 14:25

学破解第83天,《攻防世界reverse新手练习区csaw2013reversing2分析》

本帖最后由 小菜鸟一枚 于 2020-2-12 14:28 编辑

# 学破解第83天,《攻防世界reverse新手练习区csaw2013reversing2分析》
前言:
  一直对黑客充满了好奇,觉得黑客神秘,强大,无所不能,来论坛两年多了,天天看各位大佬发帖,自己只能做一个伸手党。也看了官方的入门视频教程,奈何自己基础太差,看不懂。自我反思之下,决定从今天(2019年6月17日)开始定下心来,从简单的基础教程开始学习,希望能从照抄照搬,到能独立分析,能独立破解。
  不知不觉学习了好几个月,发现自己离了教程什么都不会,不懂算法,不懂编程。随着破解学习的深入,楼主这个半吊子迷失了自我,日渐沉迷水贴装X,不能自拔。
** ==========申明:从第71天楼主开始水贴装X,帖子不再具有连续性,仅供参考,后续帖子为楼主YY专用贴!!!========== **

立帖为证!--------记录学习的点点滴滴

## 0x1查壳
  1.丢进exeinfoPE查壳,Microsoft Visual C++ v.10 - 2010程序。
  2.再看一下题目描述:听说运行就能拿到Flag,不过菜鸡运行的结果不知道为什么是乱码。

  3.运行一下程序,提示如图!
  

## 0x2上IDA
  1.将程序丢进IDA,找到main函数,F5转换一下:
```
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
int v3; // ecx
CHAR *lpMem; //
HANDLE hHeap; //

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, lpMem);
    ExitProcess(0xFFFFFFFF);
}
MessageBoxA(0, lpMem + 1, "Flag", 2u);
HeapFree(hHeap, 0, lpMem);
HeapDestroy(hHeap);
ExitProcess(0);
}
```
  2.可以看到main函数比较简单,里面就一个if语句,然后就弹窗内容为 lpMem + 1!
  3.接着去百度各个函数的意义:
HeapCreate:创建堆栈
HeapAlloc:在堆上分配内存
memcpy_s:内存拷贝函数
IsDebuggerPresent():检测调试器,成功返回1,失败返回0。
ExitProcess:退出进程
MessageBoxA:弹窗口
HeapFree:释放堆内存
HeapDestroy:销毁堆
  4.我们理一下程序的执行流程:
第一步:把409B10这个地址内的数据复制给 lpMem。
第二步:执行if语句,sub_40102A()这个函数里面return 0;再加上我们直接运行程序,IsDebuggerPresent()返回值也是0。所以这个if里面的代码块是一定不会被执行的。
第三步:弹窗,此时弹出来的是乱码!
  5. 所以我就可以猜测如果这个if执行,会不会就能输出正确的flag。if里面只有一个函数sub_401000,代码如下:
```
unsigned int __fastcall sub_401000(int a1, int a2)
{
int v2; // esi
unsigned int v3; // eax
unsigned int v4; // ecx
unsigned int result; // eax

v2 = dword_409B38;
v3 = a2 + 1 + strlen((const char *)(a2 + 1)) + 1;
v4 = 0;
result = ((v3 - (a2 + 2)) >> 2) + 1;
if ( result )
{
    do
      *(_DWORD *)(a2 + 4 * v4++) ^= v2;
    while ( v4 < result );
}
return result;
}
```
a2是我们最开始的那个lpMem参数。

## 0x3上OD
  1.将程序丢进OD,在左下角数据窗口中搜索一下给lpMem赋值的内容,看到“惶牸苎靖拖井夷珎屹摮赞摡铀競铀竟氉梯”。
  2.接下来Ctrl+G定位0040102A 到这个函数,然后查看信息窗口调用来自00401083,再次定位过去,我们看到了:
```
00401083   .E8 A2FFFFFF   call 0453d212.0040102A      ;这个call直接返回0
00401088   .85C0          test eax,eax   ;eax不为0则跳转
0040108A   .75 0A         jnz short 0453d212.00401096
0040108C   .FF15 14604000 call dword ptr ds:[<&KERNEL32.IsDebugger>; [IsDebuggerPresent
00401092   .85C0          test eax,eax      ;eax为0则跳转
00401094   .74 23         je short 0453d212.004010B9
00401096   >41            inc ecx
00401097   .41            inc ecx
00401098   .41            inc ecx
00401099   .41            inc ecx
0040109A   .CC            int3
0040109B   .8B55 F4       mov edx,dword ptr ss:         ;kernel32.7C839AD8
0040109E   .E8 5DFFFFFF   call 0453d212.00401000    /;对初始字符串解密处理
004010A3   .EB 4A         jmp short 0453d212.004010EF   ;退出程序   
004010A5   .6A 02         push 0x2                                 ; /Style = MB_ABORTRETRYIGNORE|MB_APPLMODAL
004010A7   .68 20784000   push 0453d212.00407820                   ; |Flag
004010AC   .FF75 F4       push dword ptr ss:            ; |Text = "U嬱冹SVWU鼖] 婨鰼"
004010AF   .6A 00         push 0x0                                 ; |hOwner = NULL
004010B1   .FF15 E4604000 call dword ptr ds:[<&USER32.MessageBoxA>>; \MessageBoxA
004010B7   .EB 14         jmp short 0453d212.004010CD
004010B9   >6A 02         push 0x2                                 ; /Style = MB_ABORTRETRYIGNORE|MB_APPLMODAL
004010BB   .68 20784000   push 0453d212.00407820                   ; |Flag
004010C0   .8B45 F4       mov eax,dword ptr ss:         ; |kernel32.7C839AD8
004010C3   .40            inc eax                                  ; |
004010C4   .50            push eax                                 ; |Text = 91CB4D30 ???
004010C5   .6A 00         push 0x0                                 ; |hOwner = NULL
004010C7   .FF15 E4604000 call dword ptr ds:[<&USER32.MessageBoxA>>; \MessageBoxA
004010CD   >FF75 F4       push dword ptr ss:            ; /pMemory = kernel32.7C839AD8
004010D0   .6A 00         push 0x0                                 ; |Flags = 0
004010D2   .FF75 FC       push dword ptr ss:            ; |hHeap = NULL
004010D5   .FF15 08604000 call dword ptr ds:[<&KERNEL32.HeapFree>] ; \HeapFree
004010DB   .8945 F8       mov dword ptr ss:,eax
004010DE   .FF75 FC       push dword ptr ss:            ; /hHeap = NULL
004010E1   .FF15 0C604000 call dword ptr ds:[<&KERNEL32.HeapDestro>; \HeapDestroy
004010E7   .6A 00         push 0x0                                 ; /ExitCode = 0x0
004010E9   .FF15 00604000 call dword ptr ds:[<&KERNEL32.ExitProces>; \ExitProcess
004010EF   >6A FF         push -0x1                              ; /ExitCode = 0xFFFFFFFF
004010F1   .FF15 00604000 call dword ptr ds:[<&KERNEL32.ExitProces>; \ExitProcess
```
  3.看上面这段代码,我就知道需要在0040108A 或者00401094 这里改为jmp,跳转到0040109B 这里,前面有int3中断,得跳过它执行00401000这个call。
  4.我们可以看到执行完这个call后,程序就退出了,所以我们需要跟进这个call,看看代码:
```
00401000/$56            push esi
00401001|.8B35 389B4000 mov esi,dword ptr ds:          ;华梯
00401007|.8D42 01       lea eax,dword ptr ds:   ;eax存储着解密后的flag
0040100A|.57            push edi      ;eax+1
0040100B|.8D78 01       lea edi,dword ptr ds:
0040100E|>8A08          /mov cl,byte ptr ds:
00401010|.40            |inc eax
00401011|.84C9          |test cl,cl
00401013|.^ 75 F9         \jnz short 0453d212.0040100E
00401015|.2BC7          sub eax,edi
00401017|.C1E8 02       shr eax,0x2
0040101A|.33C9          xor ecx,ecx
0040101C|.40            inc eax
0040101D|.74 08         je short 0453d212.00401027
0040101F|>31348A      /xor dword ptr ds:,esi
00401022|.41            |inc ecx
00401023|.3BC8          |cmp ecx,eax
00401025|.^ 72 F8         \jb short 0453d212.0040101F
00401027|>5F            pop edi
00401028|.5E            pop esi
00401029\.C3            retn
```
右侧的寄存器edi显示的是008F1E92,edi在eax的值上面加一了,所以在数据窗口中跟随向上翻或者看eax的值就能看到flag。


  5.出了这个call之后,就退出程序了,因为上面那段代码有两个MessageBOX,我需要判断出来后jmp需要改跳到哪一个,所以去看看原程序,是从00401094 这里跳转到004010B9 这里弹窗,综上所述,需要修改两处为:
00401094   /74 23         je short 0453d212.0040109B
004010A3   /EB 4A         jmp short 0453d212.004010B9
运行程序,弹出正确的flag!


## 0x4总结
  1.IDA和OD结合使用,确定变量的值和程序的流程。
  2. 把那个初始字符串加1弹出来的内容和原程序不一样
```
char arr[] = {0xBB,0xCC,0xA0,0xBC,0xDC,0xD1,0xBE,0xB8,0xCD,0xCF,0xBE,0xAE,0xD2,0xC4,0xAB,0x82,0xD2,
                0xD9,0x93,0xB3,0xD4,0xDE,0x93,0xA9,0xD3,0xCB,0xB8,0x82,0xD3,0xCB,0xBE,0xB99A,0xD7,0xCC,0xDD,'\0'};
      MessageBoxA(0, arr + 1, "Flag", 2u);
```
  3.调用00401000时传入的两个参数不太明白,v3+4看不懂,后面一个传的好像是初始字符串。
  4.00401000函数里面的那段解密过程也看不懂,希望有大佬不良赐教!

总结:楼主是个小菜鸟,离了教程啥都不会!

aoshixiaoyou 发表于 2020-2-13 12:25

你可以想想这帮大牛是怎么崛起的。他那个年代破解视频少的可怜。他们不是照样学的很厉害。什么原因有想过吗。重点不在教程。而在于编程,你首先得会编程理解计算机是怎么运作的。有的为了反汇编一个程序,常常自己编个类似的程序分析原理。想学好的话还是先把基础打好吧

小菜鸟一枚 发表于 2020-2-13 09:25

xvbwily 发表于 2020-2-13 08:39
入门课程从哪学起啊

学破解第71天,楼主学习记录导航贴更新(含学习资源和楼主全部学习记录)!:https://www.52pojie.cn/thread-1067012-1-1.html

天山雪 发表于 2020-2-12 14:48

加油,高手都是从菜鸟走过来的。

nimeilai 发表于 2020-2-12 14:55

你将来不可限量

宁逍遥 发表于 2020-2-12 14:55

楼主已经比大多数人要强了

redrabbit 发表于 2020-2-12 15:00

千里之行始于足下,愿我们都可以一步步走向强大!

不苦小和尚 发表于 2020-2-12 15:01

希望这种通俗易懂的

racdot 发表于 2020-2-12 15:02

对楼主莫大的鼓励和支持

wgw3721 发表于 2020-2-12 15:08

你将来不可限量

龙御风0 发表于 2020-2-12 15:13

感谢楼主分享

lsy832 发表于 2020-2-12 15:28

关注了 持续看准备学习
页: [1] 2 3 4
查看完整版本: 学破解第83天,《攻防世界reverse新手练习区csaw2013reversing2分析》