0x01 Beijing
解题过程
拖进IDA查看main函数的伪C代码如下:
int __cdecl main()
{
char v0; // al
char v1; // al
char v2; // al
char v3; // al
char v4; // al
char v5; // al
char v6; // al
char v7; // al
char v8; // al
char v9; // al
char v10; // al
char v11; // al
char v12; // al
char v13; // al
char v14; // al
char v15; // al
char v16; // al
char v17; // al
char v18; // al
char v19; // al
char v20; // al
v0 = sub_8048460(dword_804A03C);
printf("%c", v0);
fflush(stdout);
v1 = sub_8048460(dword_804A044);
printf("%c", v1);
fflush(stdout);
v2 = sub_8048460(dword_804A0E0);
printf("%c", v2);
fflush(stdout);
v3 = sub_8048460(dword_804A050);
printf("%c", v3);
fflush(stdout);
v4 = sub_8048460(dword_804A058);
printf("%c", v4);
fflush(stdout);
v5 = sub_8048460(dword_804A0E4);
printf("%c", v5);
fflush(stdout);
v6 = sub_8048460(dword_804A064);
printf("%c", v6);
fflush(stdout);
v7 = sub_8048460(dword_804A0E8);
printf("%c", v7);
fflush(stdout);
v8 = sub_8048460(dword_804A070);
printf("%c", v8);
fflush(stdout);
v9 = sub_8048460(dword_804A078);
printf("%c", v9);
fflush(stdout);
v10 = sub_8048460(dword_804A080);
printf("%c", v10);
fflush(stdout);
v11 = sub_8048460(dword_804A088);
printf("%c", v11);
fflush(stdout);
v12 = sub_8048460(dword_804A090);
printf("%c", v12);
fflush(stdout);
v13 = sub_8048460(dword_804A098);
printf("%c", v13);
fflush(stdout);
v14 = sub_8048460(dword_804A0A0);
printf("%c", v14);
fflush(stdout);
v15 = sub_8048460(dword_804A0A8);
printf("%c", v15);
fflush(stdout);
v16 = sub_8048460(dword_804A0B0);
printf("%c", v16);
fflush(stdout);
v17 = sub_8048460(dword_804A0B8);
printf("%c", v17);
fflush(stdout);
v18 = sub_8048460(dword_804A0C0);
printf("%c", v18);
fflush(stdout);
v19 = sub_8048460(dword_804A0C8);
printf("%c", v19);
fflush(stdout);
v20 = sub_8048460(dword_804A0D0);
printf("%c", v20);
fflush(stdout);
printf("\n");
return 0;
}
发现从v0到v20这21个字符都是经过sub_8048460函数后输出,那么我们跟进这个函数:
int __cdecl sub_8048460(int a1)
{
char v2; // [esp+Fh] [ebp-1h]
switch ( a1 )
{
case 0:
v2 = byte_804A021 ^ byte_804A020;
break;
case 1:
v2 = byte_804A023 ^ byte_804A022;
break;
case 2:
v2 = byte_804A025 ^ byte_804A024;
break;
case 3:
v2 = byte_804A027 ^ byte_804A026;
break;
case 4:
v2 = byte_804A029 ^ byte_804A028;
break;
case 5:
v2 = byte_804A02B ^ byte_804A02A;
break;
case 6:
v2 = byte_804A02D ^ byte_804A02C;
break;
case 7:
v2 = byte_804A02F ^ byte_804A02E;
break;
case 8:
v2 = byte_804A031 ^ byte_804A030;
break;
case 9:
v2 = byte_804A033 ^ byte_804A032;
break;
case 10:
v2 = byte_804A035 ^ byte_804A034;
break;
case 11:
v2 = byte_804A037 ^ byte_804A036;
break;
case 12:
v2 = byte_804A039 ^ byte_804A038;
break;
case 13:
v2 = byte_804A03B ^ byte_804A03A;
break;
default:
v2 = 0;
break;
}
return v2;
}
从dword_804A03C起注意第一个数字都是双字,那么从v0到v20sub_8048460函数的参数分别为:0x6,0x9,?,0x1,0xa,?,0x8,?,0xb,0x2,0x3,0x1,0xd,0x4,0x5,0x2,0x7,0x2,0x3,0x1,0xc
从byte_804A020开始的数组的值如下:
按照顺序每两个字符异或后只有switch参数是0,1,2,3,4,6的时候才是正常字符,而这显然不是我们要的结果。而我们注意到每次异或的后面一项都是正常字符时,我们大胆猜测每次异或的前面那一项是干扰项,于是可以得出v0到v20输出结果为:fl?g{?m?zing_beijing}我们知道flag的格式为flag{……},那么?代表的字符就是a,带入得到最终flag为flag{amazing_beijing}
fflush(stdout)的作用
fflush(stdout):清空标准输出缓冲区。
fflush(stdin):清空标准输入缓冲区。
在使用多个输出(输入)函数进行连续多次输出(输入)的时候,因为上一个数据还没有输出(输入)完毕,还在缓冲区的时候,下一个输出(输入)函数就将另一个数据放入缓冲区,那么就覆盖掉了上一个数据,这样就会出现错误。但是如果加入fflush()函数及时进行刷新的话就不会出现这种错误。
eg1.
#include<stdio.h>
int main()
{
char c;
scanf("%c",&c);
printf("0x%x\n",c);
scanf("%c",&c);
printf("0x%x\n",c);
return 0;
}
我们在运行这个程序的过程中,如果只输入一个字符c,那么在我们的期待中输出的应该是0x63,但是在实际运行过程中输出的却是:
我们查看ascii码表发现0xa对应的是换行,也就是enter键,这说明scanf读取了两个字符,但是像换行这种字符明显不是我们所需要的,我们修改代码:
#include<stdio.h>
int main()
{
char c;
scanf("%c",&c);
printf("0x%x\n",c);
fflush(stdin);
scanf("%c",&c);
printf("0x%x\n",c);
return 0;
}
此时输入c输出结果为0x63,控制台等待我们再一次输入然后再输出。
这才是我们想要的答案。通过这个例子我们更清楚的了解fflush(stdin)的作用。
eg2.在笔者测试的几个使用的fflush(stdout)的代码运行时看不出什么差别,若读者有好的实例欢迎分享。
0x02 Blend
解题过程
首先在kali下用“file main.bin”命令查看文件类型:
发现这可能是一个MBR主引导扇区文件。
安装qemu:
sudo apt-get install qemu
然后运行一下这个程序:
qemu-system-i386 -drive format=raw,file=main.bin
发现错误提示此命令找不到,那么我们再安装qemu-system-i386:
sudo apt-get install qemu-system-i386
可以正常运行:
然后用32位IDA的16-bit模式打开main.bin,发现汇编代码,找到标志检查位,代码分析结果如下(注释):
seg000:0066 cmp byte ptr ds:7DC8h, 13h
seg000:006B jle loc_10D
seg000:006F cmp dword ptr ds:1234h, 67616C66h ; galf
seg000:0078 jnz loc_14D
seg000:007C movaps xmm0, xmmword ptr ds:1238h ; 将flag后面的字符放入xmm0
seg000:0081 movaps xmm5, xmmword ptr ds:7C00h
seg000:0086 pshufd xmm0, xmm0, 1Eh ; 将16个字符按顺序分成4组,每组4个字符,从左到右分别是第一组到第四组,原来第一组变成第三组,第二组变成第四组,第三组变成第二组,第四组变成第一组。
seg000:008B mov si, 8
seg000:008E
seg000:008E loc_8E: ; CODE XREF: seg000:00C1↓j
seg000:008E movaps xmm2, xmm0 ; 将xmm0中的字符串给xmm2
seg000:0091 andps xmm2, xmmword ptr [si+7D90h] ; [si+7d90h]=[7d98h]
seg000:0096 psadbw xmm5, xmm2 ; 计算xmm5与xmm2中的压缩无符号字节整数的绝对差值;然后将8个低位差值单独相加,8个高位差值单独相加,以产生两个字整数结果。
seg000:0096 psadbw xmm5, xmm2 ; 计算xmm5与xmm2中的压缩无符号字节整数的绝对差值;然后将8个低位差值单独相加,8个高位差值单独相加,以产生两个字整数结果。
我们注意到很重要的一步操作的命令是psadbw,其作用简单的来说就是计算绝对差值的和,我们知道这一步计算过程是不可逆的,即使pshufd命令的排列过程可逆,最终整个算法也是不可逆的,于是,我们解决方法呼之欲出:“爆破”!
我们采用qemu+gdb的方法来进行调试,首先将gdb实例加入qemu:
qemu-system-i386 -drive format=raw,file=./main.bin -s
新开一个终端,输入:
gdb
target remote localhost:1234
set architecture i8086
break *0x7c6f
continue
然后在qemu上面随便输入一个flag开头的字符串,这里我们输入:flagabcdefghijklmnop
回到终端继续调试如下:
(gdb) nexti
0x00007c78 in ?? ()
(gdb) nexti
0x00007c7c in ?? ()
(gdb) nexti
0x00007c81 in ?? ()
(gdb) p $xmm0
$1 = {v4_float = {1.67779994e+22, 4.37102201e+24, 1.1384003e+27,
2.96401656e+29}, v2_double = {8.5408832230361244e+194,
3.9038200537988823e+233}, v16_int8 = {97, 98, 99, 100, 101, 102, 103,
104, 105, 106, 107, 108, 109, 110, 111, 112}, v8_int16 = {25185, 25699,
26213, 26727, 27241, 27755, 28269, 28783}, v4_int32 = {1684234849,
1751606885, 1818978921, 1886350957}, v2_int64 = {7523094288207667809,
8101815670912281193}, uint128 = 149452120213688298009235146691947225697}
(gdb) nexti
0x00007c86 in ?? ()
(gdb) p $xmm5
$2 = {v4_float = {-134298496, -2.50091934, -1.48039995e-36, 1.93815862e-18},
v2_double = {-8.0294250547975565, 1.241726856953559e-144}, v16_int8 = {-72,
19, 0, -51, 16, 15, 32, -64, -125, -32, -5, -125, -56, 2, 15, 34},
v8_int16 = {5048, -13056, 3856, -16352, -8061, -31749, 712, 8719},
v4_int32 = {-855632968, -1071640816, -2080644989, 571409096}, v2_int64 = {
-4602662254339419208, 2454183382171246723},
uint128 = 45271692760863909157144958299409486776}
(gdb) nexti
0x00007c8b in ?? ()
(gdb) p $xmm0
$3 = {v4_float = {1.1384003e+27, 2.96401656e+29, 4.37102201e+24,
1.67779994e+22}, v2_double = {3.9038200537988823e+233,
3.8354611286278023e+175}, v16_int8 = {105, 106, 107, 108, 109, 110, 111,
112, 101, 102, 103, 104, 97, 98, 99, 100}, v8_int16 = {27241, 27755,
28269, 28783, 26213, 26727, 25185, 25699}, v4_int32 = {1818978921,
1886350957, 1751606885, 1684234849}, v2_int64 = {8101815670912281193,
7233733596990105189}, uint128 = 133438832361070900906391932340777216617}
(gdb) nexti
0x00007c8e in ?? ()
(gdb) nexti
0x00007c91 in ?? ()
(gdb) p $xmm2
$4 = {v4_float = {1.1384003e+27, 2.96401656e+29, 4.37102201e+24,
1.67779994e+22}, v2_double = {3.9038200537988823e+233,
3.8354611286278023e+175}, v16_int8 = {105, 106, 107, 108, 109, 110, 111,
112, 101, 102, 103, 104, 97, 98, 99, 100}, v8_int16 = {27241, 27755,
28269, 28783, 26213, 26727, 25185, 25699}, v4_int32 = {1818978921,
1886350957, 1751606885, 1684234849}, v2_int64 = {8101815670912281193,
7233733596990105189}, uint128 = 133438832361070900906391932340777216617}
(gdb) nexti
0x00007c96 in ?? ()
(gdb) p $xmm2
$5 = {v4_float = {1.13839255e+27, 2.96401656e+29, 4.3709929e+24,
1.67779994e+22}, v2_double = {3.9038200537988359e+233,
3.8354611286277313e+175}, v16_int8 = {0, 106, 107, 108, 109, 110, 111,
112, 0, 102, 103, 104, 97, 98, 99, 100}, v8_int16 = {27136, 27755, 28269,
28783, 26112, 26727, 25185, 25699}, v4_int32 = {1818978816, 1886350957,
1751606784, 1684234849}, v2_int64 = {8101815670912281088,
7233733596990105088}, uint128 = 133438832361070899043270780896112503296}
(gdb) nexti
0x00007c9a in ?? ()
(gdb) p $xmm5
$6 = {v4_float = {1.15186734e-42, 0, 1.08880891e-42, 0}, v2_double = {
4.0612196088150466e-321, 3.8388900681864856e-321}, v16_int8 = {54, 3, 0,
0, 0, 0, 0, 0, 9, 3, 0, 0, 0, 0, 0, 0}, v8_int16 = {822, 0, 0, 0, 777, 0,
0, 0}, v4_int32 = {822, 0, 777, 0}, v2_int64 = {822, 777},
uint128 = 14333120145272321606454}
(gdb) nexti
0x00007c9f in ?? ()
(gdb) nexti
0x00007ca3 in ?? ()
(gdb) p $di
$7 = 822
(gdb) nexti
0x00007ca7 in ?? ()
(gdb) p $edi
$8 = 53870592
通过这些调试,我们分析出如下代码:
seg000:009A movaps xmmword ptr ds:1268h, xmm5 ; 将xmm5中的字符串放到[1268h]处。
seg000:009F mov di, ds:1268h ; di中存放的是计算绝对差值后的xmm5的高位,值为822
seg000:00A3 shl edi, 10h ; 将di中的数据移到edi的高位
seg000:00A7 mov di, ds:1270h ; di中存放的是计算绝对差值后的xmm5的低位,值为777
seg000:00AB mov dx, si ; si=8,dx=8
seg000:00AD dec dx ; dx=7
seg000:00AE add dx, dx ; dx=14
seg000:00B0 add dx, dx ; dx=28
seg000:00B2 cmp edi, [edx+7DA8h] ; edi中存放的是计算过绝对差值后的xmm5的值,1Ch(28)+7DA8h=7DB4h,7DB4h-7C00h=1B4h,在Hex View中找到1B4h处的内容:E2 02 CE 02 E2 02 C4 02 DB 02 D4 02 CD 02 D9 02 04 03 11 03
seg000:00BA jnz loc_14D ; 如果不相等就跳转到loc_14D
seg000:00BE dec si ; 如果相等si--,然后继续循环loc_8E
seg000:00BF test si, si
seg000:00C1 jnz short loc_8E
seg000:00C3 mov byte ptr ds:1278h, 0Ah
seg000:00C8 mov bx, ds:1266h
seg000:00CC mov di, 7D70h
seg000:00CF test bx, bx
seg000:00D1 jz short loc_DF
seg000:00D3 dec word ptr ds:1266h
seg000:00D7 xor cx, cx
seg000:00D9 mov dx, 14h
seg000:00DC jmp loc_38
我们发现这段代码的意思就是将计算过绝对差值后的xmm5的值与MBR中的一串数据进行对比,并且这个过程将循环8次,如果八次结果都相等,那么程序将输出“CORRECT!”。
程序的逻辑已经分析清楚了,接下来我们开始写脚本模拟整个过程:
import binascii
import struct
xmm5_start=binascii.unhexlify('220f02c883fbe083c0200f10cd0013b8')
# The data stored at 0x7DA8 and compared against esi
esi_consts = [
'F602DD02',
'E802DC02',
'ED02D802',
'E202CE02',
'E202C402',
'DB02D402',
'CD02D902',
'04031103' ]
esi_consts = [struct.unpack('<I', binascii.unhexlify(c))[0] for c in esi_consts]
esi_consts = esi_consts[::-1]
# Our 16 variables ('a' through 'p')
variables = [chr(ord('a') + i) for i in range(16)]
def esi_to_xmm5(esi):
s1 = esi % (1 << 0x10)
s2 = (esi - s1) >> (0x10)
w = struct.pack('>Q', s1) + struct.pack('>Q', s2)
return w
def print_constraints():
for i in range(8):
prev_esi = esi_consts[i-1]
xmm5 = esi_to_xmm5(prev_esi)
if i == 0:
xmm5 = xmm5_start
esi = esi_consts[i]
s1 = esi % (1 << 0x10)
s2 = (esi - s1) >> (0x10)
# sum of absolute differences between xmm5 and our flag
s = ''
for j in range(8):
if j == 7-i:
# This is the masking step
s += 'abs(0-' + str(ord(xmm5[j])) + ') + '
continue
s += 'abs(' + variables[j] + '-' + str(ord(xmm5[j])) + ') + '
s += '0 == {}, '.format(s1)
print(s)
s = ''
for j in range(8,16):
if j-8 == 7-i:
# This is the masking step
s += 'abs(0-' + str(ord(xmm5[j])) + ') + '
continue
s += 'abs(' + variables[j] + '-' + str(ord(xmm5[j])) + ') + '
s += '0 == {}, '.format(s2)
print(s)
if __name__ == '__main__':
print_constraints()
得到16个方程:
abs(a-34) + abs(b-15) + abs(c-2) + abs(d-200) + abs(e-131) + abs(f-251) + abs(g-224) + abs(0-131) + 0 == 772,
abs(i-192) + abs(j-32) + abs(k-15) + abs(l-16) + abs(m-205) + abs(n-0) + abs(o-19) + abs(0-184) + 0 == 785,
abs(a-0) + abs(b-0) + abs(c-0) + abs(d-0) + abs(e-0) + abs(f-0) + abs(0-3) + abs(h-4) + 0 == 717,
abs(i-0) + abs(j-0) + abs(k-0) + abs(l-0) + abs(m-0) + abs(n-0) + abs(0-3) + abs(p-17) + 0 == 729,
abs(a-0) + abs(b-0) + abs(c-0) + abs(d-0) + abs(e-0) + abs(0-0) + abs(g-2) + abs(h-205) + 0 == 731,
abs(i-0) + abs(j-0) + abs(k-0) + abs(l-0) + abs(m-0) + abs(0-0) + abs(o-2) + abs(p-217) + 0 == 724,
abs(a-0) + abs(b-0) + abs(c-0) + abs(d-0) + abs(0-0) + abs(f-0) + abs(g-2) + abs(h-219) + 0 == 738,
abs(i-0) + abs(j-0) + abs(k-0) + abs(l-0) + abs(0-0) + abs(n-0) + abs(o-2) + abs(p-212) + 0 == 708,
abs(a-0) + abs(b-0) + abs(c-0) + abs(0-0) + abs(e-0) + abs(f-0) + abs(g-2) + abs(h-226) + 0 == 738,
abs(i-0) + abs(j-0) + abs(k-0) + abs(0-0) + abs(m-0) + abs(n-0) + abs(o-2) + abs(p-196) + 0 == 718,
abs(a-0) + abs(b-0) + abs(0-0) + abs(d-0) + abs(e-0) + abs(f-0) + abs(g-2) + abs(h-226) + 0 == 749,
abs(i-0) + abs(j-0) + abs(0-0) + abs(l-0) + abs(m-0) + abs(n-0) + abs(o-2) + abs(p-206) + 0 == 728,
abs(a-0) + abs(0-0) + abs(c-0) + abs(d-0) + abs(e-0) + abs(f-0) + abs(g-2) + abs(h-237) + 0 == 744,
abs(i-0) + abs(0-0) + abs(k-0) + abs(l-0) + abs(m-0) + abs(n-0) + abs(o-2) + abs(p-216) + 0 == 732,
abs(0-0) + abs(b-0) + abs(c-0) + abs(d-0) + abs(e-0) + abs(f-0) + abs(g-2) + abs(h-232) + 0 == 758,
abs(0-0) + abs(j-0) + abs(k-0) + abs(l-0) + abs(m-0) + abs(n-0) + abs(o-2) + abs(p-220) + 0 == 733,
import sys
sys.path.append('z3/build/')
from z3 import *
def abs(x):
return If(x>=0,x,-x)
s = Solver()
a = Int('a')
b = Int('b')
c = Int('c')
d = Int('d')
e = Int('e')
f = Int('f')
g = Int('g')
h = Int('h')
i = Int('i')
j = Int('j')
k = Int('k')
l = Int('l')
m = Int('m')
n = Int('n')
o = Int('o')
p = Int('p')
s.add(a >= 32)
s.add(b >= 32)
s.add(c >= 32)
s.add(d >= 32)
s.add(e >= 32)
s.add(f >= 32)
s.add(g >= 32)
s.add(h >= 32)
s.add(i >= 32)
s.add(j >= 32)
s.add(k >= 32)
s.add(l >= 32)
s.add(m >= 32)
s.add(n >= 32)
s.add(o >= 32)
s.add(p >= 32)
s.add(127 > a)
s.add(127 > b)
s.add(127 > c)
s.add(127 > d)
s.add(127 > e)
s.add(127 > f)
s.add(127 > g)
s.add(127 > h)
s.add(127 > i)
s.add(127 > j)
s.add(127 > k)
s.add(127 > l)
s.add(127 > m)
s.add(127 > n)
s.add(127 > o)
s.add(127 > p)
s.add(abs(a-34) + abs(b-15) + abs(c-2) + abs(d-200) + abs(e-131) + abs(f-251) + abs(g-224) + abs(0-131) + 0 == 772)
s.add(abs(i-192) + abs(j-32) + abs(k-15) + abs(l-16) + abs(m-205) + abs(n-0) + abs(o-19) + abs(0-184) + 0 == 785)
s.add(abs(a-0) + abs(b-0) + abs(c-0) + abs(d-0) + abs(e-0) + abs(f-0) + abs(0-3) + abs(h-4) + 0 == 717)
s.add(abs(i-0) + abs(j-0) + abs(k-0) + abs(l-0) + abs(m-0) + abs(n-0) + abs(0-3) + abs(p-17) + 0 == 729)
s.add(abs(a-0) + abs(b-0) + abs(c-0) + abs(d-0) + abs(e-0) + abs(0-0) + abs(g-2) + abs(h-205) + 0 == 731)
s.add(abs(i-0) + abs(j-0) + abs(k-0) + abs(l-0) + abs(m-0) + abs(0-0) + abs(o-2) + abs(p-217) + 0 == 724)
s.add(abs(a-0) + abs(b-0) + abs(c-0) + abs(d-0) + abs(0-0) + abs(f-0) + abs(g-2) + abs(h-219) + 0 == 738)
s.add(abs(i-0) + abs(j-0) + abs(k-0) + abs(l-0) + abs(0-0) + abs(n-0) + abs(o-2) + abs(p-212) + 0 == 708)
s.add(abs(a-0) + abs(b-0) + abs(c-0) + abs(0-0) + abs(e-0) + abs(f-0) + abs(g-2) + abs(h-226) + 0 == 738)
s.add(abs(i-0) + abs(j-0) + abs(k-0) + abs(0-0) + abs(m-0) + abs(n-0) + abs(o-2) + abs(p-196) + 0 == 718)
s.add(abs(a-0) + abs(b-0) + abs(0-0) + abs(d-0) + abs(e-0) + abs(f-0) + abs(g-2) + abs(h-226) + 0 == 749)
s.add(abs(i-0) + abs(j-0) + abs(0-0) + abs(l-0) + abs(m-0) + abs(n-0) + abs(o-2) + abs(p-206) + 0 == 728)
s.add(abs(a-0) + abs(0-0) + abs(c-0) + abs(d-0) + abs(e-0) + abs(f-0) + abs(g-2) + abs(h-237) + 0 == 744)
s.add(abs(i-0) + abs(0-0) + abs(k-0) + abs(l-0) + abs(m-0) + abs(n-0) + abs(o-2) + abs(p-216) + 0 == 732)
s.add(abs(0-0) + abs(b-0) + abs(c-0) + abs(d-0) + abs(e-0) + abs(f-0) + abs(g-2) + abs(h-232) + 0 == 758)
s.add(abs(0-0) + abs(j-0) + abs(k-0) + abs(l-0) + abs(m-0) + abs(n-0) + abs(o-2) + abs(p-220) + 0 == 733)
print(s.check())
mod = s.model()
chars = [
mod[a],
mod[b],
mod[c],
mod[d],
mod[e],
mod[f],
mod[g],
mod[h],
mod[i],
mod[j],
mod[k],
mod[l],
mod[m],
mod[n],
mod[o],
mod[p] ]
print(chars)
flag = ''.join([chr(int(str(w))) for w in chars])
flag = flag[::-1]
print('flag' +flag[12:] + flag[8:12] + flag[0:4] + flag[4:8])
sat
[95, 114, 98, 109, 102, 95, 115, 105, 104, 101, 95, 95, 121, 110, 110, 117]
flagmbr_is_funny__eh
file命令
file命令是用来查看文件类型的或者编码格式。它通过查看文件的头部信息来获取文件类型。
常见命令参数及意义
-b 列出文件辨识结果时,不显示文件名称
-c 详细显示指令执行过程,便于排错或分析程序执行的情形
-f 列出文件中文件名的文件类型
-F 使用指定分隔符号替换输出文件名后的默认的":"分隔符
-i 输出mime类型的字符串
-L 直接显示符号连接所指向的文件类型
-m<魔法数字文件> 指定魔法数字文件
-z 尝试去解读压缩文件的内容
MBR(主引导记录)
主引导记录(MBR,Main Boot Record)是位于磁盘最前边的一段引导(Loader)代码。它负责磁盘操作系统(DOS)对磁盘进行读写时分区合法性的判别、分区引导信息的定位,它由磁盘操作系统(DOS)在对硬盘进行初始化时产生的。
MBR由四部分组成:主引导程序(偏移地址0000H–0088H),它负责从活动分区中装载,并运行系统引导程序。出错信息数据区,偏移地址0089H–00E1H为出错信息,00E2H–01BDH全为0字节。分区表(DPT,Disk Partition Table)含4个分区项,偏移地址01BEH–01FDH,每个分区表项长16个字节,共64字节为分区项1、分区项2、分区项3、分区项4。结束标志字,偏移地址01FE–01FF的2个字节值为结束标志55AA,如果该标志错误系统就不能启动。
SEE指令集(巨坑的浮点数运算)
- movaps:把4个对准的单精度值传送到xmm寄存器或者内存。
- pshufd:压缩双字乱序。
- addps XMM,XMM/m128:源存储器内容按双字对齐,共4个单精度浮点数与目的寄存器相加,结果送入目的寄存器,内存变量必须对齐内存16字节。
- psadbw:计算xmm5与xmm2中的压缩无符号字节整数的绝对差值;然后将8个低位差值单独相加,8个高位差值单独相加,以产生两个字整数结果。
……
0x03 Advanced
解题过程
首先我们观察到src文件的类型不明确,我们将这个文件放在kali中运行一下,如果直接运行会提示权限不够,于是我们给其增加执行权限。
chmod +x src
./src
运行后得到:
welcome, here is your identification, please keep it in your pocket: 4b404c4b5648725b445845734c735949405c414d5949725c45495a51
我们联想到题目的提示:please keep identification in your pocket :)。我们有理由相信这串数据很重要。先将其转换成ASCII码看一下:K@LKVHr[DXEsLsYI@\AMYIr\EIZQ,并得不到什么有用的信息。flag的格式应该是flag{……},我们将已知的这六个字符与字符串进行异或,发现0x2D和0x2C交替出现,我们将字符串依次异或0x2D和0x2C,得到flag为:flag{d_with_a_template_phew}