REVERSE-PRACTICE-BUUCTF-10
- [GWCTF 2019]xxor
- [HDCTF2019]Maze
- [WUSTCTF2020]level2
- [BJDCTF2020]BJD hamburger competition
[GWCTF 2019]xxor
elf文件,无壳,用ida分析
main函数的逻辑清晰,首先获取输入,为6个int64的值,然后每2个值一组,调用sub_400686函数进行变换,变换后的值存储到v11,最后验证v11,验证输入
sub_400686函数,读取每组的2个值,进行64次循环运算,变换后的值放回原位置
check函数,可以由此得到输入经变换后需要变成的6个值
写逆脚本,v11的6个值可以手动计算或者使用python的z3库计算
v5类型为int32,初始值为0,64次加法必定超出了int32的最大正值,不过计算过程中会自动截取,于是不必特别考虑v5,正常写脚本即可
#include<stdio.h>
__int64 v11[] = { 0xdf48ef7e,0x20caacf4,0xe0f30fd5,0x5c50d8d6,0x9e1bde2d,0x84f30420 };
__int64 a2[] = { 2,2,3,4 };
void main()
{for (int i = 0; i <= 4; i += 2){unsigned int v3 = v11[i];unsigned int v4 = v11[i + 1];int v5 = 0;for (int j = 0; j <= 63; j++)v5 += 1166789954;for (int j = 0; j <= 63; j++){v4-= (v3 + v5 + 20) ^ ((v3 << 6) + a2[2]) ^ ((v3 >> 9) + a2[3]) ^ 0x10;v3-= (v4 + v5 + 11) ^ ((v4 << 6) + a2[0]) ^ ((v4 >> 9) + a2[1]) ^ 0x20;v5 -= 1166789954;}if (v5 == 0){v11[i] = v3;v11[i + 1] = v4;}}for (int i = 0; i < 6; i++){printf("%ld,", v11[i]);}
}
运行结果
再用python的long_to_bytes转成字符串
[HDCTF2019]Maze
exe程序,运行后提示通过迷宫获得flag,有upx壳,脱壳后ida分析
main函数没有被ida识别为函数,原因是代码中添有花指令
jnz跳转到下一条指令,不跳转也是下一条指令,这里jnz阻碍了ida的识别,需要把jnz的整条指令nop掉
.text:0040102E处,call了一段红色地址,说明该红色地址并不存在于程序中,应该是在正确指令字节基础上添加了几个字节,变得不能被ida识别,于是需要去除多余的字节,选中红色地址,按d转换为数据,依次nop掉一些字节,看nop掉字节后ida是否能够识别成代码,发现转为数据后,nop掉第一个字节,ida就可以识别了
去除花指令的效果
选中从main函数开始到结束retn指令之间的红色.text代码,按p生成函数,F5反编译
分析main函数,wsad分别对应上下左右,初始位置为[7,0],结束位置为[5,-4]
在字符串窗口找到迷宫地图,长度为70,猜测为10x7或者7x10,由初始位置和结束位置可知,地图为7x10,即7行10列,起始点在“+”,终止点在“F”,走完迷宫即可得到flag
[WUSTCTF2020]level2
elf文件,有upx壳,脱壳后ida分析
左侧函数窗口找到main函数,在IDA View-A窗口即可看到flag
[BJDCTF2020]BJD hamburger competition
unity游戏,老八秘制小汉堡,按正确的顺序加料即可得到flag
BJD hamburger competition_Data->Managed->Assembly-CSharp.dll拖入dnSpy
找到主逻辑的部分
Md5方法对传入的参数进行md5散列,大写,取前20位
Sha1方法对传入的参数进行sha1散列,大写
Spawn方法对加料的顺序进行验证,选择不同的配料对Init.secret(初始值为0)进行不同的运算,运算的结果进行sha1散列与已知值比较,相同时程序对运算的结果进行md5散列并输出为flag
using System;
using System.Security.Cryptography;
using System.Text;
using UnityEngine;// Token: 0x02000004 RID: 4
public class ButtonSpawnFruit : MonoBehaviour
{// Token: 0x0600000A RID: 10 RVA: 0x00002110 File Offset: 0x00000310public static string Md5(string str){byte[] bytes = Encoding.UTF8.GetBytes(str);byte[] array = MD5.Create().ComputeHash(bytes);StringBuilder stringBuilder = new StringBuilder();foreach (byte b in array){stringBuilder.Append(b.ToString("X2"));}return stringBuilder.ToString().Substring(0, 20);}// Token: 0x0600000B RID: 11 RVA: 0x00002170 File Offset: 0x00000370public static string Sha1(string str){byte[] bytes = Encoding.UTF8.GetBytes(str);byte[] array = SHA1.Create().ComputeHash(bytes);StringBuilder stringBuilder = new StringBuilder();foreach (byte b in array){stringBuilder.Append(b.ToString("X2"));}return stringBuilder.ToString();}// Token: 0x0600000C RID: 12 RVA: 0x000021C8 File Offset: 0x000003C8public void Spawn(){FruitSpawner component = GameObject.FindWithTag("GameController").GetComponent<FruitSpawner>();if (component){if (this.audioSources.Length != 0){this.audioSources[Random.Range(0, this.audioSources.Length)].Play();}component.Spawn(this.toSpawn);string name = this.toSpawn.name;if (name == "汉堡底" && Init.spawnCount == 0){Init.secret += 997;}else if (name == "鸭屁股"){Init.secret -= 127;}else if (name == "胡罗贝"){Init.secret *= 3;}else if (name == "臭豆腐"){Init.secret ^= 18;}else if (name == "俘虏"){Init.secret += 29;}else if (name == "白拆"){Init.secret -= 47;}else if (name == "美汁汁"){Init.secret *= 5;}else if (name == "柠檬"){Init.secret ^= 87;}else if (name == "汉堡顶" && Init.spawnCount == 5){Init.secret ^= 127;string str = Init.secret.ToString();if (ButtonSpawnFruit.Sha1(str) == "DD01903921EA24941C26A48F2CEC24E0BB0E8CC7"){this.result = "BJDCTF{" + ButtonSpawnFruit.Md5(str) + "}";Debug.Log(this.result);}}Init.spawnCount++;Debug.Log(Init.secret);Debug.Log(Init.spawnCount);}}// Token: 0x04000005 RID: 5public GameObject toSpawn;// Token: 0x04000006 RID: 6public int spawnCount = 1;// Token: 0x04000007 RID: 7public AudioSource[] audioSources;// Token: 0x04000008 RID: 8public string result = "";
}
使用在线网站可以解出已知sha1的原始值,为1001
再对1001进行md5,转成大写,取前20位,即可得到flag
如果不使用在线网站解sha1和md5散列,写爆破脚本
#coding:utf-8
#汉堡底 +=997
#汉堡顶 ^=127
#鸭屁股 -=127 0
#胡罗贝 *=3 1
#臭豆腐 ^=18 2
#俘虏 +=29 3
#白拆 -=47 4
#美汁汁 *=5 5
#柠檬 ^=87 6
import hashlib
#从其他7种材料中选4种 加上汉堡底和汉堡顶 一共6种
for i in range(7):for j in range(7):for k in range(7):for m in range(7):secret=997 #汉堡底当作第一种材料if i==0:secret-=127elif i==1:secret*=3elif i==2:secret^=18elif i==3:secret+=29elif i==4:secret-=47elif i==5:secret*=5elif i==6:secret^=87if j==0:secret-=127elif j==1:secret*=3elif j==2:secret^=18elif j==3:secret+=29elif j==4:secret-=47elif j==5:secret*=5elif j==6:secret^=87if k==0:secret-=127elif k==1:secret*=3elif k==2:secret^=18elif k==3:secret+=29elif k==4:secret-=47elif k==5:secret*=5elif k==6:secret^=87if m == 0:secret -= 127elif m == 1:secret *= 3elif m == 2:secret ^= 18elif m == 3:secret += 29elif m == 4:secret -= 47elif m == 5:secret *= 5elif m == 6:secret ^= 87secret^=127 #最后加汉堡顶的时候,材料的种数还没有加到6h = hashlib.sha1()h.update(str(secret).encode(encoding='utf-8'))#验证sha1散列if h.hexdigest() == "DD01903921EA24941C26A48F2CEC24E0BB0E8CC7".lower():print(secret)#输出md5散列h2 = hashlib.md5()h2.update(str(secret).encode(encoding='utf-8'))print(h2.hexdigest().upper()[0:20])
运行结果