兩道花指令題目

XCTF 3rd-ZCTF-2017 QExtend-300

這個題目 還是比較難的  一個就是花指令的恢復 一個就是題目的分析

這個有兩個修復的地方 一個就是 pop/call  直接把pop call nop 就行

第二點就是 switch  每個函數的返回地址增加了  第一個增加一 第二個增加二  所以。。 需要把 函數地址下面的東西給nop了

然後nop玩 程序就很明瞭了

 

本來求 這個東西的時候想用 搜索解決 然後一直 沒有解決  只能手看  然後下面是搜索代碼   我大概知道了哪裏錯了 就是 狀態沒有判斷是不是已經走過了 但是確實 這個狀態不是很好判斷 每次開一個數組 去維護這個 狀態表 感覺會有瑕疵

然後求解的時候想用z3 發現md5這裏 怎麼也過不去 z3 好像不能md5 求值把 

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<iostream>
#include<map>
#include<time.h>
#include<queue>
#include "windows.h"
using namespace std;
struct node
{
    int s[15]= {0,0,0,1,4,0,0,0,0,2,0,0,0,3,5}; //狀態
    int value[100]= {0}; //然後是向那個方向移動 保持記錄
    int sum=0;
};
int k[15];
bool judge()//判斷搜索是否違反了邊界
{
    for(int i=0; i<4; i++)
    {
        if(k[i]>k[i+1])
        {
            return 0;
        }
    }
    for(int i=5; i<9; i++)
    {
        if(k[i]>k[i+1])
        {
            return 0;
        }
    }
    for(int i=10; i<14; i++)
    {
        if(k[i]>k[i+1])
        {
            return 0;
        }
    }
    return 1;
}
bool issuccess(int *xss)//判斷是否成功
{
    for(int i=0; i<15; i++)
    {
        if(i>=5&&i<=9)
        {
            if(xss[i]!=i-4)
                return 0;
        }
        if(xss[i]!=0)
            return 0;
    }
    return 1;
}
bool mymove(int l1,int r1,int l2,int r2)//移動東西
{
    int v2; // esi
    int v3; // eax
    /*for(int i=0;i<15;i++)
    {
        printf("%d",k[i]);
    }*/
   // printf("\n");
    if (k[r1])
    {
        v2 = r1;
        v3 = r2;
        do
        {
            if ( !k[v2] )
                break;
            --v2;
        }
        while ( v2 >= l1 );
        do
        {
            if ( !k[v3] )
                break;
            --v3;
        }
        while ( v3 >= l2 );
        k[v3] = k[v2 + 1];
        k[v2 + 1] = 0;
        if(!judge())
        {
            /* for(int ii=0;ii<15;ii++)
             {
                 if(ii%5==0)
                     printf("\n");
                 printf("%d",k[ii]);

             }
             printf("\n****************************\n");
*/
            return 0;
        }
        //printf("1\n");
        return 1;
    }
    return 0;
}
void slove()
{
    queue<node>Mynode;
    int i;
    int j;
    node ss;
    Mynode.push(ss);
    while(!Mynode.empty())
    {
        /*
        0 1->2
        1 1->3
        2 2->1
        3 2->3
        4 3->2
        5 3->1
        */
        ss=Mynode.front();
        Mynode.pop();
        if(issuccess(ss.s))
        {
            for(i=0; i<ss.sum; i++)
            {
                printf("%d",ss.value[i]);
            }
            return;
        }
        for(i=0; i<6; i++)
        {
            for(j=0; j<15; j++)
            {
                k[j]=ss.s[j];
            }
            switch(i)
            {
            case 0:
                if(mymove(0,4,5,9))
                {
                    for(j=0; j<15; j++)
                    {
                        ss.s[j]=k[j];
                    }
                    ss.value[ss.sum]=i;
                    ss.sum++;
                    Mynode.push(ss);
                    ss.sum--;
                }
                break;
            case 1:
                if(mymove(0,4,10,14))
                {
                    for(j=0; j<15; j++)
                    {
                        ss.s[j]=k[j];
                    }
                    ss.value[ss.sum]=i;
                    ss.sum++;
                    Mynode.push(ss);
                    ss.sum--;
                }
                break;
            case 2:

                if( mymove(4,9,0,4))
                {
                    for(j=0; j<15; j++)
                    {
                        ss.s[j]=k[j];
                    }
                    ss.value[ss.sum]=i;
                    ss.sum++;
                    Mynode.push(ss);
                    ss.sum--;
                }
                break;
            case 3:


                if(mymove(4,9,10,14))
                {
                    for(j=0; j<15; j++)
                    {
                        ss.s[j]=k[j];
                    }
                    ss.value[ss.sum]=i;
                    ss.sum++;
                    Mynode.push(ss);
                    ss.sum--;
                }
                break;
            case 4:

                if(mymove(10,14,4,9))
                {
                    for(j=0; j<15; j++)
                    {
                        ss.s[j]=k[j];
                    }
                    ss.value[ss.sum]=i;
                    ss.sum++;
                    Mynode.push(ss);
                    ss.sum--;
                }
                break;
            case 5:

                if( mymove(10,14,0,4))
                {
                    for(j=0; j<15; j++)
                    {
                        ss.s[j]=k[j];
                    }
                    ss.value[ss.sum]=i;
                    ss.sum++;
                    Mynode.push(ss);
                    ss.sum--;
                }
            }
        }

    }
}
int main()
{
    slove();
    printf("程序運行成功!\n");
    return 0;
}

然後下面就是求flag

#!/usr/bin/env pytho3
# -*- coding:utf-8 -*-

#from z3 import*
from hashlib import md5
'''
由於我們知道了低位 
那麼我們就可以直接爆破高位
'''
#053254104123104524104
#164365215234215635215
if __name__ =="__main__":
    high_number=[0x20,0x30,0x40,0x50,0x60,0x70]
    md5_str = '0f2e7e447593ec9af3463e9c8745b892'  
    high=[0,0,0,0,0,0]
    low_number=[1,2,3,4,5,6]
    number=[0,0,0,0,0,0,0,0]
    for high[0] in high_number:
        for high[1] in high_number:
            for high[2] in high_number:
                for high[3] in high_number:
                    for high[4] in high_number:
                        for high[5] in high_number:
                            for i in range(6):
                                number[i]=chr(high[i]+low_number[i])
                            str_md5= number[0]+number[5]+number[3]+number[2]+number[5]+number[4]+number[1]+\
                            number[0]+number[4]+number[1]+number[2]+number[3]+number[1]+number[0]+\
                            number[4]+number[5]+number[2]+number[4]+number[1]+number[0]+number[4]
                            if md5(str_md5.encode("utf8")).hexdigest() == md5_str :
                                print('ZCTF{%s}' %str_md5)

另一道題目不知道出處是哪裏的 是一個朋友發的== 

如果 有老哥知道出處 還請說一下 我加上出處

ok 先看看題目的樣子

大概就是這個樣子 

然後ida  找到按鈕事件準備f5的時候 出了錯===   

這個花指令 比上面的多了幾個地方

發現了很多的紅色點 ===  

可以變成data

然後 在 把圈到的地方 變成代碼就好了 然後 再把他們nop了 就ok了

還算是有不少地方的==

 

 發現都是不讓相等的 而且都是 9*9的數據    不讓一列的數據相等  不讓 一行的數據相等  不讓3*3裏面相等 那不就是 數獨麼 

關於數獨 南郵有一個題目 可以去看看

https://blog.csdn.net/qq_41071646/article/details/88554159

 

 然後根據腳本改一下 直接跑就行 =

 

// re_exp.cpp : 定義控制檯應用程序的入口點。
//

#include "stdafx.h"
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<iostream>
#include<map>
#include<time.h>
#include<queue>
#include "windows.h"
using namespace std;
int s[9][9] = { 0, 6, 8, 0, 0, 0, 0, 5, 0, 0, 3,
	0, 2, 0, 0, 0, 7, 6, 0, 0, 0, 0, 0, 7, 9, 0, 0,
	9, 0, 0, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 4, 0, 0,
	8, 0, 0, 0, 0, 0, 0, 3, 0, 0, 7, 1, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 4, 0, 8, 0, 5, 1, 0, 0, 0, 0, 6, 5, 0, 0, 4, 0
};
int po[9][9] = { 0, 6, 8, 0, 0, 0, 0, 5, 0, 0, 3,
0, 2, 0, 0, 0, 7, 6, 0, 0, 0, 0, 0, 7, 9, 0, 0,
9, 0, 0, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 4, 0, 0,
8, 0, 0, 0, 0, 0, 0, 3, 0, 0, 7, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 4, 0, 8, 0, 5, 1, 0, 0, 0, 0, 6, 5, 0, 0, 4, 0
};
struct ppx
{
	int x;
	int y;
} ss[100];
int sum = 0;
bool pd(int len, int t)
{
	for (int i = 0; i<9; i++)
	{
		if (s[i][ss[len].y] == t || s[ss[len].x][i] == t)
		{
			return 0;
		}
	}
	int x = (ss[len].x / 3) * 3;
	int y = (ss[len].y / 3) * 3;
	for (int i = x; i<x + 3; i++)
	{
		for (int j = y; j<y + 3; j++)
		{
			if (s[i][j] == t)
			{
				return 0;
			}
		}
	}
	return 1;
}
void dfs(int len)
{
	if (len == sum)
	{
		for (int i = 0; i<9; i++)
		{
			for (int j = 0; j<9; j++)
			{
				printf("%d ", s[i][j]);
			}
			printf("\n");
		}
		printf("flag{");
		for (int i = 0; i<9; i++)
		{
			for (int j = 0; j<9; j++)
			{
				if (po[i][j] != 0)
				{
					//printf("0");
					continue;
				}
				printf("%d%d%d",i,j,s[i][j]);
			}

		}
		printf("}\n");
		return;
	}
	for (int i = 1; i<10; i++)
	{
		if (pd(len, i))
		{
			s[ss[len].x][ss[len].y] = i;
			dfs(len + 1);
			s[ss[len].x][ss[len].y] = 0;
		}
	}
	return;
}
int main()
{
	for (int i = 0; i<9; i++)
	{
		for (int j = 0; j<9; j++)
		{
			if (s[i][j] == 0)
			{
				ss[sum].x = i;
				ss[sum].y = j;
				sum++;
			}
		}
	}
	dfs(0);

	getchar();
	system("pause");
	return 0;
}

 

 發現兩個答案都對===

flag{007034043059062081104129141155168205212221238246273284314323337342358376385402427431456463489508511526535549564572618625633647654666679682706717739752783803819822851867888}

 

flag{007039043054062081104129141155168205212221238246273284314323337342358376385402427431456463489508511526535549564572618625634647652666679683706717733759782803819822851867888}

 

 

 

 鏈接:https://pan.baidu.com/s/1eFddEUqW9zp0_JIJWXBvvQ
提取碼:k2rm
複製這段內容後打開百度網盤手機App,操作更方便哦

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章