ida反編譯主函數
需要滿足三個條件,兩個check函數和最後的v2==20,第一個函數內容爲
signed int __cdecl sub_80486CD(int a1)
{
int j; // [esp+0h] [ebp-14h]
int v3; // [esp+4h] [ebp-10h]
int i; // [esp+8h] [ebp-Ch]
int v5; // [esp+Ch] [ebp-8h]
v5 = 0;
for ( i = 0; i <= 1024 && *(_DWORD *)(4 * i + a1); i = v5 * (v5 + 1) / 2 )
{
v3 = 0;
for ( j = 0; j <= v5; ++j )
v3 += *(_DWORD *)(4 * (j + i) + a1);
if ( 1 << v5 != v3 )
return -1;
++v5;
}
return v5;
}
翻譯成c++代碼就是
int sub_80486CD(int a1[]) //傳入的參數就是輸入的數組
{
int j;
int v3;
int i;
int v5;
v5=0;
for(i=0;i<=1024&&a1[i];i=v5*(v5+1)/2) //i的值就是前v5項和 0,1,3,...
{
v3=0;
for(j=0;j<=v5;j++)
v3+=a1[j+i]; //v3代表a1數組中第i項之後v5+1個數之和 sum(a1[i],a[i+1],...,a[i+v5])
if(1<<v5 != v3) //必須要滿足2的v5次方==v3
return -1;
++v5; //v5的值 0,1,2,3,...
}
return v5;
}
這就可以分行看,當v5=0時,v3就等於a1[0],v5=1時,v3就等於a1[1]+a1[2],...
a[0]
a[1]+a[2]
a[3]+a[4]+a[5]
a[6]+a[7]+a[8]+a[9]
...
每一行的值都必須等於行號從0開始,2的行號次方,再看第二個函數
signed int __cdecl sub_8048783(int a1, signed int a2)
{
int v3; // [esp+10h] [ebp-10h]
int v4; // [esp+14h] [ebp-Ch]
signed int i; // [esp+18h] [ebp-8h]
int v6; // [esp+1Ch] [ebp-4h]
v6 = 0;
for ( i = 1; i < a2; ++i )
{
v4 = 0;
v3 = i - 1;
if ( !*(_DWORD *)(4 * i + a1) )
return 0;
while ( a2 - 1 > v3 )
{
v4 += *(_DWORD *)(4 * (v3 * (v3 + 1) / 2 + v6) + a1);
++v3;
}
if ( *(_DWORD *)(4 * (v3 * (v3 + 1) / 2 + i) + a1) != v4 )
return 0;
++v6;
}
return 1;
}
翻譯成c++代碼
int sub_8048783(int a1[],int a2)
{
int v3;
int v4;
int i;
int v6;
v6=0;
for(i=1;i<a2;i++)
{
v4=0;
v3=i-1;
if(!a1[i])
return 0;
while(a2-1>v3)
{
v4+=a1[v3*(v3+1)/2+v6];
++v3;
}
if(a1[v3*(v3+1)/2+i]!=v4)
return 0;
++v6;
}
return 1;
}
這裏我們可以添加一些代碼打印一下v4求和時a1的下標是哪些值
#include <iostream>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <cstdio>
using namespace std;
int main()
{
int a1[4000]={0};
int a2=20;
int v3;
int v4;
int i;
int v6;
v6=0;
for(i=1;i<a2;i++)
{
v4=0;
v3=i-1;
if(!a1[i])
//return 0;
while(a2-1>v3)
{
v4+=a1[v3*(v3+1)/2+v6];
cout<<v3*(v3+1)/2+v6<<endl;
++v3;
}
cout<<"\n判斷時的下標爲:"<<v3*(v3+1)/2+i<<endl<<endl;
if(a1[v3*(v3+1)/2+i]!=v4){
//return 0;
}
++v6;
}
return 0;
}
這些數字乍看之下彷彿沒什麼規律,但如果我們像上面那樣列一下就會發現規律,這裏我們只列下標看
0 //0
1 2 //1
3 4 5 //2
6 7 8 9 //3
...
171 172 ... 189 //18
190 191 192 ... 209 //19
這裏會發現要求就是每一列的和等於一列中最後一行斜下角(後一列,後一行)那個數字
兩個要求都符合楊輝三角的性質(https://baike.baidu.com/item/%E6%9D%A8%E8%BE%89%E4%B8%89%E8%A7%92/215098?fr=aladdin 第11、12條)
1. 第n行數字的和爲2^(n-1)。1=2^(1-1),1+1=2^(2-1),1+2+1=2^(3-1),1+3+3+1=2^(4-1),1+4+6+4+1=2^(5-1),1+5+10+10+5+1=2^(6-1)
2. 斜線上數字的和等於其向左(從左上方到右下方的斜線)或向右拐彎(從右上方到左下方的斜線),拐角上的數字。1+1=2,1+1+1=3,1+1+1+1=4,1+2=3,1+2+3=6,1+2+3+4=10,1+3=4,1+3+6=10,1+4=5
判斷條件v2==20的條件就是楊輝三角的層數等於20,最後附上生成輸入的楊輝三角(無空格)的c++代碼
#include <iostream>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <cstdio>
using namespace std;
int main()
{
int a[200][200]={0};
int j=1;
for(int i=1;i<=20;i++)
a[i][1]=1;
for(int i=2;i<=20;i++)
for(int j=1;j<=i;j++)
a[i][j]=a[i-1][j-1]+a[i-1][j];
for(int i=1;i<=20;i++)
for(int j=1;j<=i;j++)
cout<<a[i][j];
cout<<endl;
return 0;
}
得到字符串
1111211331146411510105116152015611721353521711828567056288119368412612684369111045120210252210120451011115516533046246233016555111112662204957929247924952206612111378286715128717161716128771528678131114913641001200230033432300320021001364911411151054551365300350056435643550053003136545510515111612056018204368800811440128701144080084368182056012016111713668023806188123761944824310243101944812376618823806801361711181538163060856818564318244375848620437583182418564856830608161531811191719693876116282713250388755829237892378755825038827132116283876969171191
到md5在線網站加密一下,得到密文,包裹上RCTF{},得到flag:RCTF{37894beff1c632010dd6d524aa9604db}