不得不说 这道题其实不算难 脱完壳 用ida查看很方便 但是感觉好久没有用过od 分析了 我就试着用了用od 分析
这个程序被加了upx壳 用esp + 修复 就ok了 然后就可以愉快的用ida了
主函数的内容其实就已经够够分析了 但是我还是用了od分析
00411B9A 6A 0C push 0xC ; 0xC
00411B9C FF15 50214300 call dword ptr ds:[<&ucrtbased.srand>] ; ucrtbase.srand
00411BA2 83C4 04 add esp,0x4 ; 上面的意思是 srand(0xC)
00411BA5 3BF4 cmp esi,esp
00411BA7 E8 7BF5FFFF call 1__.00411127
00411BAC 68 409C0000 push 0x9C40
00411BB1 6A 00 push 0x0
00411BB3 68 803D4200 push 1__.00423D80
00411BB8 E8 06F5FFFF call 1__.004110C3
00411BBD 83C4 0C add esp,0xC
00411BC0 C745 88 0100000>mov dword ptr ss:[ebp-0x78],0x1 ; 初始值是1
00411BC7 EB 09 jmp short 1__.00411BD2
00411BC9 8B45 88 mov eax,dword ptr ss:[ebp-0x78]
00411BCC 83C0 01 add eax,0x1 ; eax+1
00411BCF 8945 88 mov dword ptr ss:[ebp-0x78],eax ; ebp-0x78 +1
00411BD2 837D 88 14 cmp dword ptr ss:[ebp-0x78],0x14 ; 如果ebp-0x78 大于0x14 直接退出
00411BD6 7F 55 jg short 1__.00411C2D
00411BD8 C785 7CFFFFFF 0>mov dword ptr ss:[ebp-0x84],0x1 ; ebp-0x84 赋值为1
00411BE2 EB 0F jmp short 1__.00411BF3
00411BE4 8B85 7CFFFFFF mov eax,dword ptr ss:[ebp-0x84]
00411BEA 83C0 01 add eax,0x1
00411BED 8985 7CFFFFFF mov dword ptr ss:[ebp-0x84],eax
00411BF3 8B85 7CFFFFFF mov eax,dword ptr ss:[ebp-0x84] ; 那么每次循环 就是eax初始化为1
00411BF9 3B45 88 cmp eax,dword ptr ss:[ebp-0x78] ; eax 大于ebp-0x78里面的值 退出
00411BFC 7F 2D jg short 1__.00411C2B
00411BFE 8BF4 mov esi,esp
00411C00 FF15 4C214300 call dword ptr ds:[<&ucrtbased.rand>] ; ucrtbase.rand
00411C06 3BF4 cmp esi,esp
00411C08 E8 1AF5FFFF call 1__.00411127
00411C0D 99 cdq
00411C0E B9 A0860100 mov ecx,0x186A0
00411C13 F7F9 idiv ecx
00411C15 6945 88 9001000>imul eax,dword ptr ss:[ebp-0x78],0x190
00411C1C 8B8D 7CFFFFFF mov ecx,dword ptr ss:[ebp-0x84]
00411C22 899488 38A14100 mov dword ptr ds:[eax+ecx*4+0x41A138],edx ; 从这其实就可以看出来是二位数组了 而且是int
00411C29 ^ EB B9 jmp short 1__.00411BE4
00411C2B ^ EB 9C jmp short 1__.00411BC9
00411C2D 68 307B4100 push 1__.00417B30 ; input your key with your operation can get the maximum:
00411C32 E8 16F7FFFF call 1__.0041134D
00411C37 83C4 04 add esp,0x4
00411C3A 8D45 94 lea eax,dword ptr ss:[ebp-0x6C]
00411C3D 50 push eax
00411C3E 68 747B4100 push 1__.00417B74 ; %s
00411C43 E8 01F6FFFF call 1__.00411249
00411C48 83C4 08 add esp,0x8
00411C4B 8D45 94 lea eax,dword ptr ss:[ebp-0x6C]
00411C4E 50 push eax
00411C4F E8 79F4FFFF call 1__.004110CD ; 求出输入的长度
00411C54 83C4 04 add esp,0x4
00411C57 83F8 13 cmp eax,0x13 ; 长度保存在了eax
00411C5A 74 2B je short 1__.00411C87
00411C5C 68 787B4100 push 1__.00417B78 ; error\n
00411C61 E8 E7F6FFFF call 1__.0041134D
00411C66 83C4 04 add esp,0x4
00411C69 8BF4 mov esi,esp
00411C6B 68 807B4100 push 1__.00417B80 ; pause
00411C70 FF15 48214300 call dword ptr ds:[<&ucrtbased.system>] ; ucrtbase.system
00411C76 83C4 04 add esp,0x4
00411C79 3BF4 cmp esi,esp
00411C7B E8 A7F4FFFF call 1__.00411127
00411C80 33C0 xor eax,eax
00411C82 E9 41010000 jmp 1__.00411DC8
00411C87 8D45 94 lea eax,dword ptr ss:[ebp-0x6C]
00411C8A 50 push eax
00411C8B E8 BFF4FFFF call 1__.0041114F ; 改变
00411C90 83C4 04 add esp,0x4
00411C93 C785 70FFFFFF 0>mov dword ptr ss:[ebp-0x90],0x0
00411C9D C785 7CFFFFFF 0>mov dword ptr ss:[ebp-0x84],0x1
00411CA7 8B85 7CFFFFFF mov eax,dword ptr ss:[ebp-0x84]
00411CAD 8945 88 mov dword ptr ss:[ebp-0x78],eax
00411CB0 6945 88 9001000>imul eax,dword ptr ss:[ebp-0x78],0x190
00411CB7 8B8D 7CFFFFFF mov ecx,dword ptr ss:[ebp-0x84]
00411CBD 8B15 783D4200 mov edx,dword ptr ds:[0x423D78]
00411CC3 039488 38A14100 add edx,dword ptr ds:[eax+ecx*4+0x41A138]
00411CCA 8915 783D4200 mov dword ptr ds:[0x423D78],edx
00411CD0 83BD 70FFFFFF 1>cmp dword ptr ss:[ebp-0x90],0x13 ; 循环 0x13
00411CD7 0F8D BF000000 jge 1__.00411D9C
00411CDD 8B85 70FFFFFF mov eax,dword ptr ss:[ebp-0x90]
00411CE3 0FBE4C05 94 movsx ecx,byte ptr ss:[ebp+eax-0x6C]
00411CE8 83F9 4C cmp ecx,0x4C ; a0x4c ?? ascii码为 L
00411CEB 75 29 jnz short 1__.00411D16
00411CED 8B45 88 mov eax,dword ptr ss:[ebp-0x78]
00411CF0 83C0 01 add eax,0x1
00411CF3 8945 88 mov dword ptr ss:[ebp-0x78],eax ; ebp-0x78 值+1
00411CF6 694D 88 9001000>imul ecx,dword ptr ss:[ebp-0x78],0x190
00411CFD 8B95 7CFFFFFF mov edx,dword ptr ss:[ebp-0x84]
00411D03 A1 783D4200 mov eax,dword ptr ds:[0x423D78]
00411D08 038491 38A14100 add eax,dword ptr ds:[ecx+edx*4+0x41A138]
00411D0F A3 783D4200 mov dword ptr ds:[0x423D78],eax ; 0x423d78 应该是存储在我们值
00411D14 EB 72 jmp short 1__.00411D88
00411D16 8B85 70FFFFFF mov eax,dword ptr ss:[ebp-0x90]
00411D1C 0FBE4C05 94 movsx ecx,byte ptr ss:[ebp+eax-0x6C]
00411D21 83F9 52 cmp ecx,0x52 ; 这里我并没有输入 0x52输入字符串却变化了
00411D24 75 3A jnz short 1__.00411D60
00411D26 8B45 88 mov eax,dword ptr ss:[ebp-0x78]
00411D29 83C0 01 add eax,0x1
00411D2C 8945 88 mov dword ptr ss:[ebp-0x78],eax
00411D2F 8B8D 7CFFFFFF mov ecx,dword ptr ss:[ebp-0x84]
00411D35 83C1 01 add ecx,0x1 ; 这里ebp-0x78 ebp-0x84 都+1
00411D38 898D 7CFFFFFF mov dword ptr ss:[ebp-0x84],ecx
00411D3E 6955 88 9001000>imul edx,dword ptr ss:[ebp-0x78],0x190 ; edx=[ebp-0x78]*400
00411D45 8B85 7CFFFFFF mov eax,dword ptr ss:[ebp-0x84]
00411D4B 8B0D 783D4200 mov ecx,dword ptr ds:[0x423D78]
00411D51 038C82 38A14100 add ecx,dword ptr ds:[edx+eax*4+0x41A138] ; 4*(edx*100+eax)+41a138 4是字节的意思
然后改变那个函数的分析就是
00411960 c405 8d41b887 les eax,fword ptr ds:[0x87b8418d]
00411966 ^ 79 B8 jns short 1__.00411920
00411968 17 pop ss
00411969 79 2D jns short 1__.00411998
0041196B 8F41 B8 pop dword ptr ds:[ecx-0x48] ; 1__.<ModuleEntryPoint>
0041196E 2105 0404847D and dword ptr ds:[0x7D840404],eax ; 是每隔一位 异或一次0x4
00411974 014C87 CC add dword ptr ds:[edi+eax*4-0x34],ecx
00411978 FA cli
00411979 44 inc esp
0041197A 81C4 70108F41 add esp,0x418F1070
00411980 0C 07 or al,0x7
emmm 这里有个知识点 就是 如果随机种子固定的话 随机数 也是固定的 (计算机做不到真正的随机) 有时候我们会把时间作为种子 就是为了 让随机更加随机 emmm 那我们先把 随机数打印出来
77
5628 6232
29052 1558 26150
12947 29926 11981 22371
4078 28629 4665 2229 24699
27370 3081 18012 24965 2064 26890
21054 5225 11777 29853 2956 22439 3341
31337 14755 5689 24855 4173 32304 292 5344
15512 12952 1868 10888 19581 13463 32652 3409 28353
26151 14598 12455 26295 25763 26040 8285 27502 15148 4945
26170 1833 5196 9794 26804 2831 11993 2839 9979 27428 6684
4616 30265 5752 32051 10443 9240 8095 28084 26285 8838 18784 6547
7905 8373 19377 18502 27928 13669 25828 30502 28754 32357 2843 5401 10227
22871 20993 8558 10009 6581 22716 12808 4653 24593 21533 9407 6840 30369 2330
3 28024 22266 19327 18114 18100 15644 21728 17292 8396 27567 2002 3830 12564 1420
29531 21820 9954 8319 10918 7978 24806 30027 17659 8764 3258 20719 6639 23556 25786 11048
3544 31948 22 1591 644 25981 26918 31716 16427 15551 28157 7107 27297 24418 24384 32438 22224
12285 12601 13235 21606 2516 13095 27080 16331 23295 20696 31580 28758 10697 4730 16055 22208 2391 20143
16325 24537 16778 17119 18198 28537 11813 1490 21034 1978 6451 2174 24812 28772 5283 6429 15484 29353 5942
7299 6961 32019 24731 29103 17887 17338 26840 13216 8789 12474 24299 19818 18218 14564 31409 5256 31930 26804 9736
然后到这一步 我就不知道要干什么了 参考了一下大牛们的博客 我才明白 这是让求和的
然后注意上面还有会变化我们说的那个值 异或0x4 所以我们先求出最大和吧。。
然后最大和 的 是 RRRRRLLRRRLRLRRRLRL 下面是 c语言代码
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <fstream>
#include <climits>
#include <bitset>
#define digui 19
int ans[100000];
int as=0;
char s[20];
char ss[20];
void slove(int i,int j,int sum)
{
if(i>digui||i<j)
{
return;
}
if(i==digui)
{
if(as<sum)
{
ss[i+1]='\0';
as=sum;
strcpy(s,ss);
}
return;
}
sum+=ans[i*100+j];
ss[i]='L';
slove(i+1,j,sum);
ss[i]='R';
slove(i+1,j+1,sum);
sum-=ans[i*100+j];
}
int main()
{
srand(0xCu);
for(int i=0;i<20;i++)
{
for(int j=0;j<=i;j++)
{
ans[i*100 + j] = rand() % 100000;
}
}
slove(0,0,0);
printf("%s\n",s);
return 0;
}
那么 这还没有完 因为还有一个异或 所以我们要把异或处理一下 最后结果是
结果跑出来是 RVRVRHLVRVLVLVRVLVL