拿到题目运行一下
可以看到大致意思是找出一个数字要等于上方的这一串数据,放入IDA中看算法。
找到关键位置
unsigned __int64 __fastcall loadQuestion(unsigned int a1)
{
int v1; // eax
signed int v3; // [rsp+14h] [rbp-1Ch]
signed int i; // [rsp+18h] [rbp-18h]
signed int j; // [rsp+1Ch] [rbp-14h]
__int64 v6; // [rsp+20h] [rbp-10h]
unsigned __int64 v7; // [rsp+28h] [rbp-8h]
v7 = __readfsqword(0x28u);
printf("This is time %d, load questions...\n", a1);
v6 = question(a1);
v3 = 0;
for ( i = 0; i <= 3; ++i )
{
for ( j = 0; j <= 99; ++j )
{
printf("testing number %d\n", (unsigned int)j);
if ( func1(j) == v6 || func2(j) == v6 || func3(j) == v6 || func4(j) == v6 )
{
printf("\n=============> Found number, is %d\n", (unsigned int)j);
v3 = 1;
v1 = key++;
S[v1] = j;
break;
}
}
if ( v3 )
break;
printf("func%d is bad\n", (unsigned int)i);
}
if ( !v3 )
{
puts("system error, Exit!");
exit(0);
}
return __readfsqword(0x28u) ^ v7;
程序逻辑大致为找8个数字,要求这8个数字在4个函数中只要一个满足能够等于这8个数字,8个数字如下
0x15F958A7E94CA61D, 0x18B3C1D91E77DECD, 0x20AC81D87D7EE6A3, 0x339FDF470F9FFFE0, 0x33DB76A7C594BFC3, 0x5226BC958D01E7E3, 0x6A241FC4441BADF3, 0x846597CABA82E6AC]
,这八个数次找到了flag依次就是这8个数字。。。。下图为强制修改跳转所得
unsigned __int64 __fastcall func1(unsigned __int64 a1)
{
unsigned __int64 v2; // rbx
if ( a1 > 0x63 )
{
puts("Boom!");
exit(0);
}
if ( a1 <= 2 )
return a1;
v2 = func1(a1 - 1);
return v2 + func1(a1 - 2);
}
unsigned __int64 __fastcall func2(unsigned __int64 a1)
{
unsigned __int64 v2; // rbx
unsigned __int64 v3; // rbx
if ( a1 > 0x63 )
{
puts("Boom!");
exit(0);
}
if ( a1 <= 3 )
return a1;
v2 = func2(a1 - 1);
v3 = func2(a1 - 2) + v2;
return v3 + func2(a1 - 3);
}
unsigned __int64 __fastcall func3(unsigned __int64 a1)
{
unsigned __int64 v2; // rbx
unsigned __int64 v3; // rbx
unsigned __int64 v4; // rbx
if ( a1 > 0x63 )
{
puts("Boom!");
exit(0);
}
if ( a1 <= 4 )
return a1;
v2 = func3(a1 - 1);
v3 = func3(a1 - 2) + v2;
v4 = func3(a1 - 3) + v3;
return v4 + func3(a1 - 4);
}
]unsigned __int64 __fastcall func4(unsigned __int64 a1)
{
unsigned __int64 v2; // rbx
unsigned __int64 v3; // rbx
unsigned __int64 v4; // rbx
unsigned __int64 v5; // rbx
if ( a1 > 0x63 )
{
puts("Boom!");
exit(0);
}
if ( a1 <= 5 )
return a1;
v2 = func4(a1 - 1);
v3 = func4(a1 - 2) + v2;
v4 = func4(a1 - 3) + v3;
v5 = func4(a1 - 4) + v4;
return v5 + func4(a1 - 5);
}
是一个类似于斐波那契数列的算法。。。由于采用了递归导致计算速度过于缓慢,导致难以计算出结果,将其算法优化一下。
同时我们需要注意等于的数据为__ int64,而返回的数据为unsigned __int64 因此最好这题的代码用c将数据类型定义好。进行计算
四份计算代码如下
#include
#include
unsigned __int64 f(int n) {
// write code here
unsigned __int64 f0 = 1;
unsigned __int64 f1 = 2;
unsigned __int64 f2 = 0;
for (int i = 2; i < n; i++){
f2 = f0 + f1;
f0 = f1;
f1 = f2;
}
return f2;
}
int main()
{
__int64 a[8] = { 0x15F958A7E94CA61D, 0x18B3C1D91E77DECD, 0x20AC81D87D7EE6A3, 0x339FDF470F9FFFE0, 0x33DB76A7C594BFC3, 0x5226BC958D01E7E3, 0x6A241FC4441BADF3, 0x846597CABA82E6AC };
for (int x = 0; x <= 7; x++)
{
for (int i = 10; i <= 0x63; i++)
{
if (f(i) == a[x])
{
printf("%d=====>%llx\n", i, a[x]);
}
}
}
system("pause");
}
#include
#include
unsigned __int64 fib1(int n) {
// write code here
unsigned __int64 f0 = 1;
unsigned __int64 f1 = 2;
unsigned __int64 f2 = 4;
unsigned __int64 f3=0;
for (int i = 6; i < n; i++){
f3 = f0 + f1+f2;
f0 = f1;
f1 = f2;
f2 = f3;
}
return f3;
}
unsigned __int64 fib2(int n) {
// write code here
unsigned __int64 f0 = 1;
unsigned __int64 f1 = 2;
unsigned __int64 f2 = 3;
unsigned __int64 f3=0;
for (int i = 6; i < n; i++){
f3 = f0 + f1 + f2;
f0 = f1;
f1 = f2;
f2 = f3;
}
return f3;
}
unsigned __int64 fib3(int n) {
// write code here
unsigned __int64 f0 = 1;
unsigned __int64 f1 = 1;
unsigned __int64 f2 = 2;
unsigned __int64 f3=0;
for (int i = 6; i < n; i++){
f3 = f0 + f1 + f2;
f0 = f1;
f1 = f2;
f2 = f3;
}
return f3;
}
int main()
{
__int64 a[8] = { 0x15F958A7E94CA61D, 0x18B3C1D91E77DECD, 0x20AC81D87D7EE6A3, 0x339FDF470F9FFFE0, 0x33DB76A7C594BFC3, 0x5226BC958D01E7E3, 0x6A241FC4441BADF3, 0x846597CABA82E6AC };
for (int x = 0; x <= 7; x++)
{
for (int i = 10; i <= 0x63; i++)
{
if (fib1(i) * 3 + 2 * fib2(i) + fib3(i) == a[x])
{
printf("%d=====>%llx\n", i,a[x]);
}
}
}
system("pause");
}
#include
#include
unsigned __int64 fib1(int n) {
// write code here
unsigned __int64 f0 = 1;
unsigned __int64 f1 = 2;
unsigned __int64 f2 = 4;
unsigned __int64 f3=8;
unsigned __int64 f4;
for (int i = 8; i < n; i++){
f4 = f0 + f1 + f2+f3;
f0 = f1;
f1 = f2;
f2 = f3;
f3 = f4;
}
return f3;
}
unsigned __int64 fib2(int n) {
// write code here
unsigned __int64 f0 = 1;
unsigned __int64 f1 = 2;
unsigned __int64 f2 = 4;
unsigned __int64 f3=7;
unsigned __int64 f4;
for (int i = 8; i < n; i++){
f4 = f0 + f1 + f2+f3;
f0 = f1;
f1 = f2;
f2 = f3;
f3 = f4;
}
return f3;
}
unsigned __int64 fib3(int n) {
// write code here
unsigned __int64 f0 = 1;
unsigned __int64 f1 = 2;
unsigned __int64 f2 = 3;
unsigned __int64 f3=6;
unsigned __int64 f4;
for (int i = 8; i < n; i++){
f4 = f0 + f1 + f2+f3;
f0 = f1;
f1 = f2;
f2 = f3;
f3 = f4;
}
return f3;
}
unsigned __int64 fib4(int n) {
// write code here
unsigned __int64 f0 = 1;
unsigned __int64 f1 = 1;
unsigned __int64 f2 = 2;
unsigned __int64 f3 = 4;
unsigned __int64 f4;
for (int i = 8; i < n; i++){
f4 = f0 + f1 + f2 + f3;
f0 = f1;
f1 = f2;
f2 = f3;
f3 = f4;
}
return f3;
}
int main()
{
__int64 a[8] = { 0x15F958A7E94CA61D, 0x18B3C1D91E77DECD, 0x20AC81D87D7EE6A3, 0x339FDF470F9FFFE0, 0x33DB76A7C594BFC3, 0x5226BC958D01E7E3, 0x6A241FC4441BADF3, 0x846597CABA82E6AC };
for (int x = 0; x <= 7; x++)
{
for (int i = 10; i <= 0x63; i++)
{
if (fib1(i) * 4 + 3 * fib2(i) + 2 * fib3(i) + fib4(i) == a[x])
{
printf("%d======>%llx\n", i,a[x]);
}
}
}
system("pause");
}
#include
#include
unsigned __int64 fib1(int n) {
// write code here
unsigned __int64 f0 = 1;
unsigned __int64 f1 = 2;
unsigned __int64 f2 = 4;
unsigned __int64 f3 = 8;
unsigned __int64 f4=16;
unsigned __int64 f5;
for (int i = 10; i < n; i++){
f5 = f0 + f1 + f2 + f3+f4;
f0 = f1;
f1 = f2;
f2 = f3;
f3 = f4;
f4 = f5;
}
return f4;
}
unsigned __int64 fib2(int n) {
// write code here
unsigned __int64 f0 = 1;
unsigned __int64 f1 = 2;
unsigned __int64 f2 = 4;
unsigned __int64 f3 = 8;
unsigned __int64 f4 = 15;
unsigned __int64 f5;
for (int i = 10; i < n; i++){
f5 = f0 + f1 + f2 + f3 + f4;
f0 = f1;
f1 = f2;
f2 = f3;
f3 = f4;
f4 = f5;
}
return f4;
}
unsigned __int64 fib3(int n) {
// write code here
unsigned __int64 f0 = 1;
unsigned __int64 f1 = 2;
unsigned __int64 f2 = 4;
unsigned __int64 f3 = 7;
unsigned __int64 f4 = 14;
unsigned __int64 f5;
for (int i = 10; i < n; i++){
f5 = f0 + f1 + f2 + f3 + f4;
f0 = f1;
f1 = f2;
f2 = f3;
f3 = f4;
f4 = f5;
}
return f4;
}
unsigned __int64 fib4(int n) {
// write code here
unsigned __int64 f0 = 1;
unsigned __int64 f1 = 2;
unsigned __int64 f2 = 3;
unsigned __int64 f3 = 6;
unsigned __int64 f4 = 12;
unsigned __int64 f5;
for (int i = 10; i < n; i++){
f5 = f0 + f1 + f2 + f3 + f4;
f0 = f1;
f1 = f2;
f2 = f3;
f3 = f4;
f4 = f5;
}
return f4;
}
unsigned __int64 fib5(int n) {
// write code here
unsigned __int64 f0 = 1;
unsigned __int64 f1 = 1;
unsigned __int64 f2 = 2;
unsigned __int64 f3 = 4;
unsigned __int64 f4 = 8;
unsigned __int64 f5;
for (int i = 10; i < n; i++){
f5 = f0 + f1 + f2 + f3 + f4;
f0 = f1;
f1 = f2;
f2 = f3;
f3 = f4;
f4 = f5;
}
return f4;
}
int main()
{
__int64 a[8] = { 0x15F958A7E94CA61D, 0x18B3C1D91E77DECD, 0x20AC81D87D7EE6A3, 0x339FDF470F9FFFE0, 0x33DB76A7C594BFC3, 0x5226BC958D01E7E3, 0x6A241FC4441BADF3, 0x846597CABA82E6AC };
for (int x = 0; x <= 7;x++)
{
for (int i = 11; i <= 0x63; i++)
{
if (fib1(i) * 5 + 4 * fib2(i) + 3 * fib3(i) + 2 * fib4(i) + fib5(i) == a[x])
{
printf("%d=====>%llx\n", i, a[x]);
}
}
}
system("pause");
}
最后计算出的结果为
99=====>6a241fc4441badf3
88=====>846597caba82e6ac
88=====>18b3c1d91e77decd
99=====>33db76a7c594bfc3
77=====>15f958a7e94ca61d
66=====>5226bc958d01e7e3
66======>20ac81d87d7ee6a3
77======>339fdf470f9fffe0
将其整理为flag为。。
flag{77_88_66_77_99_66_99_88}