02--网鼎杯第一场

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指令集(巨坑的浮点数运算)
  1. movaps:把4个对准的单精度值传送到xmm寄存器或者内存。
  2. pshufd:压缩双字乱序。
  3. addps XMM,XMM/m128:源存储器内容按双字对齐,共4个单精度浮点数与目的寄存器相加,结果送入目的寄存器,内存变量必须对齐内存16字节。
  4. 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}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值