南郵ctf知識點彙總 - re篇

Hello,RE!:

open 1.exe文件,按F5還原代碼

把帶V的變量從int還原成char

獲得倒序flag

 

ReadAsm2:

00000000004004e6 <func>:
  4004e6: 55                    push   rbp
  4004e7: 48 89 e5              mov    rbp,rsp
  4004ea: 48 89 7d e8           mov    QWORD PTR [rbp-0x18],rdi //輸入值 input[] rdi=input
  4004ee: 89 75 e4              mov    DWORD PTR [rbp-0x1c],esi //28 esi=28
  4004f1: c7 45 fc 01 00 00 00  mov    DWORD PTR [rbp-0x4],0x1  //i=1
  4004f8: eb 28                 jmp    400522 <func+0x3c> //跳到400522
  4004fa: 8b 45 fc              mov    eax,DWORD PTR [rbp-0x4] //eax=i
  4004fd: 48 63 d0              movsxd rdx,eax //rdx=eax=i
  400500: 48 8b 45 e8           mov    rax,QWORD PTR [rbp-0x18] //rax=input[0]
  400504: 48 01 d0              add    rax,rdx //rax=input[rdx]=input[i]
  400507: 8b 55 fc              mov    edx,DWORD PTR [rbp-0x4] //edx=i
  40050a: 48 63 ca              movsxd rcx,edx //rcx=i
  40050d: 48 8b 55 e8           mov    rdx,QWORD PTR [rbp-0x18] //rdx=input[0]
  400511: 48 01 ca              add    rdx,rcx //rdx=input[i]
  400514: 0f b6 0a              movzx  ecx,BYTE PTR [rdx] //ecx=rdx=input[i]
  400517: 8b 55 fc              mov    edx,DWORD PTR [rbp-0x4] //edx=i
  40051a: 31 ca                 xor    edx,ecx //edx=edx xor ecx
  40051c: 88 10                 mov    BYTE PTR [rax],dl //rax=dl
  40051e: 83 45 fc 01           add    DWORD PTR [rbp-0x4],0x1 //i+=1 
  400522: 8b 45 fc              mov    eax,DWORD PTR [rbp-0x4] //eax=i
  400525: 3b 45 e4              cmp    eax,DWORD PTR [rbp-0x1c] // 比較 eax 28
  400528: 7e d0                 jle    4004fa <func+0x14> //如果 eax=i<=28,跳到 4004fa
  40052a: 90                    nop
  40052b: 5d                    pop    rbp
  40052c: c3                    ret
input = [0x0, 0x67, 0x6e, 0x62, 0x63, 0x7e, 0x74, 0x62, 0x69, 0x6d,
                  0x55, 0x6a, 0x7f, 0x60, 0x51, 0x66, 0x63, 0x4e, 0x66, 0x7b,
                  0x71, 0x4a, 0x74, 0x76, 0x6b, 0x70, 0x79, 0x66 , 0x1c]

i=1
while i<=28:
  input[i]=input[i]^i
  i+=1
print "".join([chr(c) for c in input])

 

Py交易:

https://tool.lu/pyc/

在線反編譯:

import base64

def encode(message):
    s = ''
    for i in message:
        x = ord(i) ^ 32
        x = x + 16
        s += chr(x)
    
    return base64.b64encode(s)

correct = 'XlNkVmtUI1MgXWBZXCFeKY+AaXNt'
flag = ''
print 'Input flag:'
flag = raw_input()
if encode(flag) == correct:
    print 'correct'
else:
    print 'wrong'

根據代碼編寫一個decode函數,並且decode代碼裏的correct變量內容XlNkVmtUI1MgXWBZXCFeKY+AaXNt :

def decode(em):
	em=base64.b64decode(em)
	s=""
	for i in em:
		x=ord(i)-16
		x=x^32
		x=chr(x)
		s+=x
	return s
print decode("XlNkVmtUI1MgXWBZXCFeKY+AaXNt")

 

WxyVM

elf文件,在ida中打開,獲得源碼

查看dword_601060的內容:

.data:0000000000601060 ; int dword_601060[]
.data:0000000000601060 dword_601060    dd 0FFFFFFC4h, 34h, 22h, 0FFFFFFB1h, 0FFFFFFD3h, 11h, 0FFFFFF97h
.data:0000000000601060                                         ; DATA XREF: main+6Er
.data:0000000000601060                 dd 7, 0FFFFFFDBh, 37h, 0FFFFFFC4h, 6, 1Dh, 0FFFFFFFCh
.data:0000000000601060                 dd 5Bh, 0FFFFFFEDh, 0FFFFFF98h, 0FFFFFFDFh, 0FFFFFF94h
.data:0000000000601060                 dd 0FFFFFFD8h, 0FFFFFFB3h, 0FFFFFF84h, 0FFFFFFCCh, 8

 

處理字符串的sub_4005B6爲:

__int64 sub_4005B6()
{
  unsigned int v0; // ST04_4@3
  __int64 result; // rax@3
  signed int i; // [sp+0h] [bp-10h]@1
  char v3; // [sp+8h] [bp-8h]@3

  for ( i = 0; i <= 14999; i += 3 )
  {
    v0 = byte_6010C0[(signed __int64)i];
    v3 = byte_6010C0[(signed __int64)(i + 2)];
    result = v0;
    switch ( v0 )
    {
      case 1u:
        result = byte_6010C0[(signed __int64)(i + 1)];
        *(&byte_604B80 + result) += v3;
        break;
      case 2u:
        result = byte_6010C0[(signed __int64)(i + 1)];
        *(&byte_604B80 + result) -= v3;
        break;
      case 3u:
        result = byte_6010C0[(signed __int64)(i + 1)];
        *(&byte_604B80 + result) ^= v3;
        break;
      case 4u:
        result = byte_6010C0[(signed __int64)(i + 1)];
        *(&byte_604B80 + result) *= v3;
        break;
      case 5u:
        result = byte_6010C0[(signed __int64)(i + 1)];
        *(&byte_604B80 + result) ^= *(&byte_604B80 + byte_6010C0[(signed __int64)(i + 2)]);
        break;
      default:
        continue;
    }
  }
  return result;
}

主要處理方式是截取byte_6010c0中每三個元素爲一組,第一個元素作爲運算方式,利用switch判斷,第二個元素爲byte_604B80中待處理元素的位置,第三個元素爲處理使用的數值

寫腳本逆向運算獲得flag

import struct

buf=idaapi.get_many_bytes(0x601060, 24*4) #獲得dword_601060的所有byte

#每4個byte轉爲一個int存入數組
dw_601060=[]
i=0
while i<24*4:
	dw_601060.append((struct.unpack("i", buf[i:i+4])[0]))
	i+=4

byte_6010C0=idaapi.get_many_bytes(0x6010C0, 15000)#獲取byte_6010C0的所有byte

#逆向sub_400586
def sub_400586_re(byte_6010C0,dw_601060):
	result=0
	for i in [j for j in range(14999,-1,-1) if j%3==0]:#倒序循環
		v0=struct.unpack("i", bytearray([byte_6010C0[i],'\x00','\x00','\x00']))[0]#將需要的byte轉爲int使用
		v3=struct.unpack("i", bytearray([byte_6010C0[i+2],'\x00','\x00','\x00']))[0]
		result=struct.unpack("i", bytearray([byte_6010C0[i+1],'\x00','\x00','\x00']))[0]
		if v0==1:
			dw_601060[result]-=v3
		elif v0==2:
			dw_601060[result]+=v3
		elif v0==3:
			dw_601060[result]^=v3
		elif v0==4:
			dw_601060[result]/=v3
		elif v0==5:
			dw_601060[result]^=dw_601060[v3]
	print ''.join([str(chr(int(i)&0x00FF))for i in dw_601060])
	return result

sub_400586_re(byte_6010C0,dw_601060)

 

maze:

elf文件,導入ida

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  const char *v3; // rsi@2
  signed __int64 v4; // rbx@4
  signed int v5; // eax@5
  char v6; // bp@5
  char v7; // al@8
  const char *v8; // rdi@19
  __int64 v10; // [sp+0h] [bp-28h]@1

  v10 = 0LL;
  puts("Input flag:");
  scanf("%s", &s1, 0LL);
  if ( strlen(&s1) != 24 || (v3 = "nctf{", strncmp(&s1, "nctf{", 5uLL)) || *(&byte_6010BF + 24) != 125 )
  {
LABEL_22:
    puts("Wrong flag!");
    exit(-1);
  }
  v4 = 5LL;
  if ( strlen(&s1) - 1 > 5 )
  {
    while ( 1 )
    {
      v5 = *(&s1 + v4);
      v6 = 0;
      if ( v5 > 'N' )
      {
        v5 = (unsigned __int8)v5;
        if ( (unsigned __int8)v5 == 'O' )
        {
          v7 = sub_400650((_DWORD *)&v10 + 1);
          goto LABEL_14;
        }
        if ( v5 == 'o' )
        {
          v7 = sub_400660((char *)&v10 + 4, v3);
          goto LABEL_14;
        }
      }
      else
      {
        v5 = (unsigned __int8)v5;
        if ( (unsigned __int8)v5 == '.' )
        {
          v7 = sub_400670(&v10, v3);
          goto LABEL_14;
        }
        if ( v5 == '0' )
        {
          v7 = sub_400680(&v10, v3);
LABEL_14:
          v6 = v7;
          goto LABEL_15;
        }
      }
LABEL_15:
      v3 = (const char *)HIDWORD(v10);
      if ( !(unsigned __int8)sub_400690((__int64)asc_601060, SHIDWORD(v10), v10) )
        goto LABEL_22;
      if ( ++v4 >= strlen(&s1) - 1 )
      {
        if ( v6 )
          break;
LABEL_20:
        v8 = "Wrong flag!";
        goto LABEL_21;
      }
    }
  }
  if ( *(&asc_601060[8 * (signed int)v10] + SHIDWORD(v10)) != 35 )
    goto LABEL_20;
  v8 = "Congratulations!";
LABEL_21:
  puts(v8);
  return 0LL;
}

很多goto,先看while(1)的終止break

LABEL_15:
      v3 = (const char *)HIDWORD(v10);
      if ( !(unsigned __int8)sub_400690((__int64)asc_601060, SHIDWORD(v10), v10) )
        goto LABEL_22;
      if ( ++v4 >= strlen(&s1) - 1 )
      {
        if ( v6 )
          break;

第一個if如果不通過就會goto 22 wrong flag,查看sub_400690內容:

__int64 __fastcall sub_400690(__int64 a1, int a2, int a3)
{
  __int64 result; // rax@1

  result = *(_BYTE *)(a1 + a2 + 8LL * a3);
  LOBYTE(result) = (_DWORD)result == 32 || (_DWORD)result == 35;
  return result;
}

return true的條件是result==32或者35

 

查看asc_601060的內容:

'  *******   *  **** * ****  * ***  *#  *** *** ***     *********'

32和35對應空格和#號

推測asc_601060應該爲一個8*8迷宮

目標應該是到達#號位置

繼續看break的條件,還有一個v6==True,回到label 14發現v6=v7,v7又一系列判斷產生:

查看sub_400650,660,670,680的代碼

分別爲 x-1,並判斷>0,x+1,並判斷<8,作用爲移動,並且判斷是否出界

分析一下

v10是64位int型

當v5==O:

      v10的高位字節-1,v6爲界限判定

當v5==o:

      v10的高位字節+1,v6爲界限判定

當v5==.:

      v10的低位字節-1,v6爲界限判定

當v5==0:

      v10的低位字節+1,v6爲界限判定

 

再看sub_400690

SHIDWORD取的是高位字節,判斷出高位字節爲行數,低位字節爲列數

所以Oo.0分別爲左右上下

起始v10=0LL,(0,0)

走迷宮:

o0oo00O000oooo..OO

獲得flag

 

WxyVM 2

elf文件,放入ida

25000+行,decompile需要一定時間

輸入長度25的byte_694100

byte_694100與dword_694060相同則通過

獲取dword_694060的內容

import struct

buf=idaapi.get_many_bytes(0x694060, 25*4) 

dw=[]
i=0
while i<25*4:
	dw.append((struct.unpack("i", buf[i:i+4])[0]))
	i+=4
#print [hex(n) for n in dw]
print dw

[-64, -123, -7, 108, -30, 20, -69, -28, 13, 89, 28, 35, -120, 110, -101, -54, -70, 92, 55, -1, 72, -40, 31, -85, -91]

提取包含byte_694100到byte_694119的行,並且生成進行逆運算的文件:

file=open("WxyVM2.main",'r')
lines=[]
for l in file:
	start=0x694100
	end=0x694100+25
	for i in range(start,end):
		if "byte_"+hex(i).replace("0x","").upper() in l:
			l=l.strip()
			if "+" in l:
				l=l.replace("+","-")
			elif "-" in l:
				l=l.replace("-","+")

			if "++" in l:
				l=l.replace("++","")
				l=l.replace(";","")
				l=l+"+=1"

			if "--" in l:
				l=l.replace("--","")
				l=l.replace(";","")
				l=l+"-=1"
			l=l.replace("byte_"+hex(i).replace("0x","").upper(),"byte_694100_array["+str((i-start))+"]")
			l=l.replace("u;",";")
			l=l.replace(";","")
			lines.append(l)
print len(lines)
f= open("wxyvm2_re.py","w+")
f.write("byte_694100_array=[-64, -123, -7, 108, -30, 20, -69, -28, 13, 89, 28, 35, -120, 110, -101, -54, -70, 92, 55, -1, 72, -40, 31, -85, -91]\n\n")

for i in range(len(lines)):
	f.write(lines[-i-1]+"\n")
f.write("print ''.join([chr(n&0x00ff) for n in byte_694100_array])")
f.close()

這裏主要是從main函數中,去掉首尾的部分,提取包含byte_694100-694119(ord+25)的行(694119不包含在區間內),這些行加減逆運算,++與--換爲python語法,格式轉換後,倒序寫入到wxyvm2_re.py中,這個文件還包含dword_694060的內容,對dword_694060進行逆運算,最後運行python wxyvm2_re.py獲得flag

 

你大概需要一個優秀的mac:

mach-o文件,導入ida

查看main函數:

得知v4長度爲56

查看func1以及xfunc1-5

查看check函數,發現input最終需要與&unk_100000ED0開始的224個字節長度數組相同

獲得目標數組:

import struct

buf=idaapi.get_many_bytes(0x100000ED0, 224) 

dw=[]
i=0
while i<224:
	dw.append((struct.unpack("i", buf[i:i+4])[0]))
	i+=4
#print [hex(n) for n in dw]
print dw


[21, 31, 18, 20, 8, 58, 70, 44, 7, 27, 81, 19, 63, 87, 8, 5, 63, 48, 50, 81, 82, 2, 110, 120, 22, 124, 110, 97, 112, 72, 28, 59, 50, 42, 19, 69, 7, 42, 24, 12, 110, 65, 112, 4, 6, 110, 92, 0, 66, 69, 112, 90, 2, 4, 14, 76]

編寫func1,xfunc1-5的逆運算:

def func1_re(a1):
	for i in range(55,-1,-1):
 		a1[i]^=0xDE
 	return a1

def xfunc1_re(a1):
	for i in range(9,-1,-1):
 		a1[i]^=0xAD
 	return a1

def xfunc2_re(a1):
	for i in range(9,-1,-1):
 		a1[i+10]^=0xBE
 	return a1

def xfunc3_re(a1):
	for i in range(9,-1,-1):
 		a1[i+20]^=0xEF
 	return a1

def xfunc4_re(a1):
	for i in range(9,-1,-1):
 		a1[i+30]^=0xAB
 	return a1

def xfunc5_re(a1):
	for i in range(15,-1,-1):
 		a1[i+40]^=0xEF
 	return a1


target=[21, 31, 18, 20, 8, 58, 70, 44, 7, 27, 81, 19, 63, 87, 8, 5, 63, 48, 50, 81, 82, 2, 110, 120, 22, 124, 110, 97, 112, 72, 28, 59, 50, 42, 19, 69, 7, 42, 24, 12, 110, 65, 112, 4, 6, 110, 92, 0, 66, 69, 112, 90, 2, 4, 14, 76]

target=xfunc5_re(target)
target=xfunc4_re(target)
target=xfunc3_re(target)
target=xfunc2_re(target)
target=xfunc1_re(target)
target=func1_re(target)

print ''.join([chr(n) for n in target])

獲得flag

 

HomuraVM:

elf文件,導入ida

main函數中發現:

爲關鍵部分

查看sub_8DC

sub_8AA:

8AA爲反調試代碼

關鍵在sub_8DC

這裏會跳去其他地址執行,先打印出所有可能跳去的地址:

首先獲得dword_1048的內容:

import struct

buf=idaapi.get_many_bytes(0x0000000000001048, 59*4) 

dw=[]
i=0
while i<59*4:
	dw.append((struct.unpack("i", buf[i:i+4])[0]))
	i+=4
print dw

[-1505, -1061, -1061, -1061, -1442, -1061, -1061, -1061, -1061, -1061, -1554, -1061, -1061, -1061, -1061, -1061, -1061, -1408, -1061, -1061, -1061, -1061, -1061, -1061, -1374, -1061, -1303, -1061, -1061, -1061, -1626, -1061, -1061, -1061, -1061, -1061, -1061, -1804, -1061, -1061, -1061, -1061, -1728, -1061, -1766, -1061, -1061, -1660, -1061, -1061, -1694, -1592, -1061, -1061, -1061, -1061, -1211, -1061, -1146]

獲得jmp地址:

def sub_8DC(a1,dword_1048):
  for c in a1:
    v1=ord(c)-67
    if v1<=0x3A:#58
      #(char *)dword_1048 + dword_1048[(unsigned __int64)(unsigned int)v1];
      print c+":"+hex((int(0x1048&0xFF)+dword_1048[v1])&0xffffffff)
      

a1=set("h[ur]ovMCh{mG}hv{aG}[ur]ovaaaMCh{mG}hv{aG}[ur]ovrrMCh{mG}hv{aG}[ur]ovrararaMCh{mG}hv{aG}[ur]ovrararrrMCh{mG}hv{aG}[ur]ovararaaMCh{mG}hv{aG}[ur]ovrararraraMCh{mG}hv{aG}[ur]ovrrrarrrMCh{mG}hv{aG}[ur]ovaarrarrMCh{mG}hv{aG}[ur]ovaaarrarMCh{mG}hv{aG}[ur]ovrrrarrMCh{mG}hv{aG}[ur]ovaarrraaMCh{mG}hv{aG}[ur]ovarraarMCh{mG}hv{aG}[ur]ovrrraaarrMCh{mG}hv{aG}[ur]ovaaarrrrarrMCh{mG}hv{aG}[ur]ovrrrraarrarrMCh{mG}hv{aG}[ur]ovrrarraMCh{mG}hv{aG}[ur]ovaaraarMCh{mG}")
dword_1048=[-1505, -1061, -1061, -1061, -1442, -1061, -1061, -1061, -1061, -1061, -1554, -1061, -1061, -1061, -1061, -1061, -1061, -1408, -1061, -1061, -1061, -1061, -1061, -1061, -1374, -1061, -1303, -1061, -1061, -1061, -1626, -1061, -1061, -1061, -1061, -1061, -1061, -1804, -1061, -1061, -1061, -1061, -1728, -1061, -1766, -1061, -1061, -1660, -1061, -1061, -1694, -1592, -1061, -1061, -1061, -1061, -1211, -1061, -1146]
sub_8DC(a1,dword_1048)

a:0xfffff9eeL
C:0xfffffa67L
G:0xfffffaa6L
h:0xfffff93cL
M:0xfffffa36L
m:0xfffff988L
o:0xfffff962L
r:0xfffff9ccL
u:0xfffff9aaL
v:0xfffffa10L
}:0xfffffbceL
[:0xfffffaeaL
]:0xfffffb31L
{:0xfffffb8dL

在ida的反彙編頁面disassambly找到對應的部分

//a:0xfffff9eeL
.text:00000000000009EE                 mov     rax, cs:qword_202080
.text:00000000000009F5                 mov     edx, [rax]
.text:00000000000009F7                 sub     edx, 1
.text:00000000000009FA                 mov     [rax], edx
.text:00000000000009FC                 mov     eax, cs:dword_202074
.text:0000000000000A02                 add     eax, 1
.text:0000000000000A05                 mov     cs:dword_202074, eax
.text:0000000000000A0B                 jmp     loc_C23

//C:0xfffffa67L
.text:0000000000000A67                 mov     rax, cs:qword_202088
.text:0000000000000A6E                 mov     edx, [rax]
.text:0000000000000A70                 mov     rax, cs:qword_202080
.text:0000000000000A77                 mov     ecx, [rax]
.text:0000000000000A79                 mov     rax, cs:qword_202078
.text:0000000000000A80                 mov     eax, [rax]
.text:0000000000000A82                 and     eax, ecx
.text:0000000000000A84                 lea     ecx, [rax+rax]
.text:0000000000000A87                 mov     rax, cs:qword_202088
.text:0000000000000A8E                 sub     edx, ecx
.text:0000000000000A90                 mov     [rax], edx
.text:0000000000000A92                 mov     eax, cs:dword_202074
.text:0000000000000A98                 add     eax, 1
.text:0000000000000A9B                 mov     cs:dword_202074, eax
.text:0000000000000AA1                 jmp     loc_C23

//G:0xfffffaa6L
.text:0000000000000AA6                 mov     rax, cs:qword_202088
.text:0000000000000AAD                 mov     edx, [rax]
.text:0000000000000AAF                 sub     edx, 1
.text:0000000000000AB2                 mov     [rax], edx
.text:0000000000000AB4                 mov     eax, cs:dword_202074
.text:0000000000000ABA                 add     eax, 1
.text:0000000000000ABD                 mov     cs:dword_202074, eax
.text:0000000000000AC3                 jmp     loc_C23


//h:0xfffff93cL
.text:000000000000093C                 mov     rax, cs:qword_202078
.text:0000000000000943                 add     rax, 4
.text:0000000000000947                 mov     cs:qword_202078, rax
.text:000000000000094E                 mov     eax, cs:dword_202074
.text:0000000000000954                 add     eax, 1
.text:0000000000000957                 mov     cs:dword_202074, eax
.text:000000000000095D                 jmp     loc_C23

//M:0xfffffa36L
.text:0000000000000A36                 mov     rax, cs:qword_202080
.text:0000000000000A3D                 mov     ecx, [rax]
.text:0000000000000A3F                 mov     rax, cs:qword_202078
.text:0000000000000A46                 mov     edx, [rax]
.text:0000000000000A48                 mov     rax, cs:qword_202088
.text:0000000000000A4F                 add     edx, ecx
.text:0000000000000A51                 mov     [rax], edx
.text:0000000000000A53                 mov     eax, cs:dword_202074
.text:0000000000000A59                 add     eax, 1
.text:0000000000000A5C                 mov     cs:dword_202074, eax
.text:0000000000000A62                 jmp     loc_C23

//m:0xfffff988L
.text:0000000000000988                 mov     rax, cs:qword_202078
.text:000000000000098F                 mov     edx, [rax]
.text:0000000000000991                 add     edx, 1
.text:0000000000000994                 mov     [rax], edx
.text:0000000000000996                 mov     eax, cs:dword_202074
.text:000000000000099C                 add     eax, 1
.text:000000000000099F                 mov     cs:dword_202074, eax
.text:00000000000009A5                 jmp     loc_C23

//o:0xfffff962L
.text:0000000000000962                 mov     rax, cs:qword_202078
.text:0000000000000969                 sub     rax, 4
.text:000000000000096D                 mov     cs:qword_202078, rax
.text:0000000000000974                 mov     eax, cs:dword_202074
.text:000000000000097A                 add     eax, 1
.text:000000000000097D                 mov     cs:dword_202074, eax
.text:0000000000000983                 jmp     loc_C23

//r:0xfffff9ccL
.text:00000000000009CC                 mov     rax, cs:qword_202080
.text:00000000000009D3                 mov     edx, [rax]
.text:00000000000009D5                 add     edx, 1
.text:00000000000009D8                 mov     [rax], edx
.text:00000000000009DA                 mov     eax, cs:dword_202074
.text:00000000000009E0                 add     eax, 1
.text:00000000000009E3                 mov     cs:dword_202074, eax
.text:00000000000009E9                 jmp     loc_C23

//u:0xfffff9aaL
.text:00000000000009AA                 mov     rax, cs:qword_202078
.text:00000000000009B1                 mov     edx, [rax]
.text:00000000000009B3                 sub     edx, 1
.text:00000000000009B6                 mov     [rax], edx
.text:00000000000009B8                 mov     eax, cs:dword_202074
.text:00000000000009BE                 add     eax, 1
.text:00000000000009C1                 mov     cs:dword_202074, eax
.text:00000000000009C7                 jmp     loc_C23

//v:0xfffffa10L
.text:0000000000000A10                 mov     rdx, cs:qword_202080
.text:0000000000000A17                 mov     rax, cs:qword_202088
.text:0000000000000A1E                 mov     edx, [rdx]
.text:0000000000000A20                 mov     [rax], edx
.text:0000000000000A22                 mov     eax, cs:dword_202074
.text:0000000000000A28                 add     eax, 1
.text:0000000000000A2B                 mov     cs:dword_202074, eax
.text:0000000000000A31                 jmp     loc_C23

//}:0xfffffbceL
.text:0000000000000BCE                 mov     rax, cs:qword_202088
.text:0000000000000BD5                 mov     eax, [rax]
.text:0000000000000BD7                 test    eax, eax
.text:0000000000000BD9                 jz      short loc_C13
.text:0000000000000BDB                 nop
.text:0000000000000BDC
.text:0000000000000BDC loc_BDC:                                ; CODE XREF: sub_8DC+324j
.text:0000000000000BDC                 mov     eax, cs:dword_202074
.text:0000000000000BE2                 sub     eax, 1
.text:0000000000000BE5                 mov     cs:dword_202074, eax
.text:0000000000000BEB                 mov     eax, cs:dword_202074
.text:0000000000000BF1                 movsxd  rdx, eax
.text:0000000000000BF4                 mov     rax, [rbp+var_8]
.text:0000000000000BF8                 add     rax, rdx
.text:0000000000000BFB                 movzx   eax, byte ptr [rax]
.text:0000000000000BFE                 cmp     al, 7Bh
.text:0000000000000C00                 jnz     short loc_BDC
.text:0000000000000C02                 mov     eax, cs:dword_202074
.text:0000000000000C08                 add     eax, 1
.text:0000000000000C0B                 mov     cs:dword_202074, eax
.text:0000000000000C11                 jmp     short loc_C22
.text:0000000000000C13 loc_C13:                                ; CODE XREF: sub_8DC+2FDj
.text:0000000000000C13                 mov     eax, cs:dword_202074
.text:0000000000000C19                 add     eax, 1
.text:0000000000000C1C                 mov     cs:dword_202074, eax
.text:0000000000000C22
.text:0000000000000C22 loc_C22:                                ; CODE XREF: sub_8DC+335j
.text:0000000000000C22                 nop

//[:0xfffffaeaL
.text:0000000000000AEA                 mov     rax, cs:qword_202078
.text:0000000000000AF1                 mov     eax, [rax]
.text:0000000000000AF3                 test    eax, eax
.text:0000000000000AF5                 jnz     short loc_B1D
.text:0000000000000AF7                 nop
.text:0000000000000AF8
.text:0000000000000AF8 loc_AF8:                                ; CODE XREF: sub_8DC+23Aj
.text:0000000000000AF8                 mov     eax, cs:dword_202074
.text:0000000000000AFE                 lea     edx, [rax+1]
.text:0000000000000B01                 mov     cs:dword_202074, edx
.text:0000000000000B07                 movsxd  rdx, eax
.text:0000000000000B0A                 mov     rax, [rbp+var_8]
.text:0000000000000B0E                 add     rax, rdx
.text:0000000000000B11                 movzx   eax, byte ptr [rax]
.text:0000000000000B14                 cmp     al, 5Dh
.text:0000000000000B16                 jnz     short loc_AF8
.text:0000000000000B18                 jmp     loc_C23
.text:0000000000000B1D loc_B1D:                                ; CODE XREF: sub_8DC+219j
.text:0000000000000B1D                 mov     eax, cs:dword_202074
.text:0000000000000B23                 add     eax, 1
.text:0000000000000B26                 mov     cs:dword_202074, eax
.text:0000000000000B2C                 jmp     loc_C23

//]:0xfffffb31L
.text:0000000000000B31                 mov     rax, cs:qword_202078
.text:0000000000000B38                 mov     eax, [rax]
.text:0000000000000B3A                 test    eax, eax
.text:0000000000000B3C                 jz      short loc_B79
.text:0000000000000B3E                 nop
.text:0000000000000B3F
.text:0000000000000B3F loc_B3F:                                ; CODE XREF: sub_8DC+287j
.text:0000000000000B3F                 mov     eax, cs:dword_202074
.text:0000000000000B45                 sub     eax, 1
.text:0000000000000B48                 mov     cs:dword_202074, eax
.text:0000000000000B4E                 mov     eax, cs:dword_202074
.text:0000000000000B54                 movsxd  rdx, eax
.text:0000000000000B57                 mov     rax, [rbp+var_8]
.text:0000000000000B5B                 add     rax, rdx
.text:0000000000000B5E                 movzx   eax, byte ptr [rax]
.text:0000000000000B61                 cmp     al, 5Bh
.text:0000000000000B63                 jnz     short loc_B3F
.text:0000000000000B65                 mov     eax, cs:dword_202074
.text:0000000000000B6B                 add     eax, 1
.text:0000000000000B6E                 mov     cs:dword_202074, eax
.text:0000000000000B74                 jmp     loc_C23
.text:0000000000000B79
.text:0000000000000B79 loc_B79:                                ; CODE XREF: sub_8DC+260j
.text:0000000000000B79                 mov     eax, cs:dword_202074
.text:0000000000000B7F                 add     eax, 1
.text:0000000000000B82                 mov     cs:dword_202074, eax
.text:0000000000000B88                 jmp     loc_C23

//{:0xfffffb8dL
.text:0000000000000B8D                 mov     rax, cs:qword_202088
.text:0000000000000B94                 mov     eax, [rax]
.text:0000000000000B96                 test    eax, eax
.text:0000000000000B98                 jnz     short loc_BBD
.text:0000000000000B9A                 nop
.text:0000000000000B9B
.text:0000000000000B9B loc_B9B:                                ; CODE XREF: sub_8DC+2DDj
.text:0000000000000B9B                 mov     eax, cs:dword_202074
.text:0000000000000BA1                 lea     edx, [rax+1]
.text:0000000000000BA4                 mov     cs:dword_202074, edx
.text:0000000000000BAA                 movsxd  rdx, eax
.text:0000000000000BAD                 mov     rax, [rbp+var_8]
.text:0000000000000BB1                 add     rax, rdx
.text:0000000000000BB4                 movzx   eax, byte ptr [rax]
.text:0000000000000BB7                 cmp     al, 7Dh
.text:0000000000000BB9                 jnz     short loc_B9B
.text:0000000000000BBB                 jmp     short loc_C23
.text:0000000000000BBD
.text:0000000000000BBD loc_BBD:                                ; CODE XREF: sub_8DC+2BCj
.text:0000000000000BBD                 mov     eax, cs:dword_202074
.text:0000000000000BC3                 add     eax, 1
.text:0000000000000BC6                 mov     cs:dword_202074, eax
.text:0000000000000BCC                 jmp     short loc_C23

翻譯一下:

#a:0xfffff9eeL
qword_202080 -= 1
dword_202074 += 1

#C:0xfffffa67L
qword_202088 -= 2 * ([qword_202078] & qword_202080)
dword_202074 += 1

#G:0xfffffaa6L
qword_202088 -= 1
dword_202074 += 1

#h:0xfffff93cL
qword_202078 += 4
dword_202074 += 1 

#M:0xfffffa36L
qword_202088 = [qword_202078] + qword_202080
dword_202074 += 1

#m:0xfffff988L
[qword_202078] += 1
dword_202074 += 1

#o:0xfffff962L
qword_202078 -= 4
dword_202074 += 1

#r:0xfffff9ccL
qword_202080 += 1
dword_202074 += 1

#u:0xfffff9aaL
[qword_202078] -= 1
dword_202074 += 1

#v:0xfffffa10L
qword_202088 = qword_202080
dword_202074 += 1

#}:0xfffffbceL
if qword_202088 == 0:
	dword_202074 += 1
else:
	while al != 0x7B: #7B=>{
		dword_202074 -= 1
		var_8 += dword_202074
	dword_202074 += 1

#[:0xfffffaeaL
if [qword_202078] == 0:
	while al != 0x5D:#]
		dword_202074 += 1
		var_8 += dword_202074
else:
	dword_202074 += 1

#]:0xfffffb31L
if [qword_202078] == 0:
	dword_202074 += 1
else:
	while al != 0x5B: #[
		dword_202074 -= 1
		var_8  += dword_202074
	dword_202074 += 1

#{:0xfffffb8dL
if qword_202088 == 0:
	while al != 0x7D: #}
		dword_202074 += 1
		var_8 += dword_202074
else:
	dword_202074 += 1

分析一下,有四個循環,

遇到[,

        如果078爲0,則直接快進到],繼續程序

        如果078不爲0,則正常運行

遇到],

        如果078爲0,則正常運行

        如果078不爲0,則返回到之前的[位置

遇到{,

        如果088爲0,則直接快進到},繼續程序

        如果088不爲0,則正常運行

遇到},

        如果088爲0,則正常運行

        如果088不爲0,則返回到之前的{位置

發現循環只有三種:

[ur]:   [078] -= 1 , [080] += 1, 直到[078]==0

{mG}:   [078] += 1 , [088] -= 1, 直到[088]==0

{aG}:   [080] -= 1 , [088] -= 1, 直到[088]==0

觀察到h是078+=4,爲前進一個dword的長度,所以每個h的之後的指令就是對當前dword的操作,操作完成後下一個h指令使地址向前一個dword,所以利用h分割指令 v40 v39

h[ur]ovMCh{mG}
hv{aG}[ur]ovaaaMCh{mG}
hv{aG}[ur]ovrrMCh{mG}
hv{aG}[ur]ovrararaMCh{mG}
hv{aG}[ur]ovrararrrMCh{mG}
hv{aG}[ur]ovararaaMCh{mG}
hv{aG}[ur]ovrararraraMCh{mG}
hv{aG}[ur]ovrrrarrrMCh{mG}
hv{aG}[ur]ovaarrarrMCh{mG}
hv{aG}[ur]ovaaarrarMCh{mG}
hv{aG}[ur]ovrrrarrMCh{mG}
hv{aG}[ur]ovaarrraaMCh{mG}
hv{aG}[ur]ovarraarMCh{mG}
hv{aG}[ur]ovrrraaarrMCh{mG}
hv{aG}[ur]ovaaarrrrarrMCh{mG}
hv{aG}[ur]ovrrrraarrarrMCh{mG}
hv{aG}[ur]ovrrarraMCh{mG}
hv{aG}[ur]ovaaraarMCh{mG}
hv{aG}[ur]ovrrarraMCh{mG}
hv{aG}[ur]ovaarrrarMCh{mG}
hv{aG}[ur]ovrraarraMCh{mG}
hv{aG}[ur]ovrrarMCh{mG}
hv{aG}[ur]ovaarrarMCh{mG}
hv{aG}[ur]ovrrraarMCh{mG}
hv{aG}[ur]ovrrrraaMCh{mG}
hv{aG}[ur]ovrrarraMCh{mG}
hv{aG}[ur]ovrrrrrrMCh{mG}
hv{aG}[ur]ovaaaarMCh{mG}
hv{aG}[ur]ovrraaaMCh{mG}
hv{aG}[ur]ovaarraMCh{mG}
hv{aG}[ur]ovrrarMCh{mG}
hv{aG}[ur]ovaarraaMCh{mG}
hv{aG}[ur]ovaarraraMCh{mG}
hv{aG}[ur]ovaarrararMCh{mG}

發現指令的格式:

h:
qword_202078 += 4
dword_202074 += 1

v:
qword_202088 = qword_202080
dword_202074 += 1

{aG}:   
[080] -= 1 , [088] -= 1, 直到[088]==0

[ur]:   
[078] -= 1 , [080] += 1, 直到[078]==0

o:
qword_202078 -= 4
dword_202074 += 1

v:
qword_202088 = qword_202080
dword_202074 += 1


...


M:
qword_202088 = s[qword_202078] + qword_202080
dword_202074 += 1

C:
qword_202088 -= 2 * (s[qword_202078] & qword_202080)
dword_202074 += 1

h:
qword_202078 += 4
dword_202074 += 1 

{mG}:
[078] += 1 , [088] -= 1, 直到[088]==0

分析一下

h:
向右前進一個dword: d[i]

v:
[088]=[080]

{aG}:   
[080] = 0 //[080] -= [088],因爲[088]==[080],所以[080]==0
[088] = 0

[ur]:   
[080] = [078] //[080] += [078], 因爲[080]=0,所以[080]=[078]
[078] = 0

o:
倒退一個dword: d[i-1]

v:
[088]=[080] //[088]=d[i],[080]=d[i]


... r或者a
//r: [080]+=1
//a: [080]-=1
//設操作爲f
//[080]=f(d[i])


M:
[088] = [078] + [080] //[078]==d[i-1], 所以[088] = d[i-1] + f(d[i])

C:
[088] -= 2 * ([078] & [080]) //[088] = d[i-1] + f(d[i]) - 2*(d[i-1] & f(d[i]))

h:
前進一個字符

{mG}:
[078] += [088] //[078]已經爲0,所以[078]=d[i-1] + f(d[i]) - 2*(d[i-1] & f(d[i]))
[088] = 0

所以修改dword的公式g爲:

g爲最終的結果,由main中獲得:

g=[27,114,17,118,8,74,126,5,55,124,31,88,104,7,112,7,49,108,4,47,4,105,54,77,127,8,80,12,109,28,127,80,29,96]

暴力破解,循環string.printable,找到對應的f

import string
g=[27,114,17,118,8,74,126,5,55,124,31,88,104,7,112,7,49,108,4,47,4,105,54,77,127,8,80,12,109,28,127,80,29,96]

f=[]
for i in range(0,len(g)-1):
  found=False
  for tmpf in string.printable:
    if g[i+1]==g[i]+ord(tmpf)-2*(g[i]&ord(tmpf)):
      f.append(tmpf)
      found=True
      break
  if not found:
    print "failed"
    break
print f

f爲:['i', 'c', 'g', '~', 'B', '4', '{', '2', 'K', 'c', 'G', '0', 'o', 'w', 'w', '6', ']', 'h', '+', '+', 'm', '_', '{', '2', 'w', 'X', '\\', 'a', 'q', 'c', '/', 'M', '}']

因爲i=0開始循環,所以f[0]=f1(s1),第一行指令跳過

根據指令找到f的操作

aaa
rr
rarara
rararrr
araraa
rararrara
rrrarrr
aarrarr
aaarrar
rrrarr
aarrraa
arraar
rrraaarr
aaarrrrarr
rrrraarrarr
rrarra
aaraar
rrarra
aarrrar
rraarra
rrar
aarrar
rrraar
rrrraa
rrarra
rrrrrr
aaaar
rraaa
aarra
rrar
aarraa
aarrara
aarrarar

a爲-1,r爲+1,需要逆運算所以取相反數:

list_080=[]
flines=open("f_lines.txt","r")
for line in flines:
  list_080.append(-(line.count('r')-line.count('a'))) 
print list_080

list_080爲:[3, -2, 0, -3, 2, -1, -5, -1, 1, -4, 1, 0, -2, -2, -5, -2, 2, -2, -1, -1, -2, 0, -2, -2, -2, -6, 3, 1, 1, -2, 2, 1, 0]

對f數組進行逆運算獲得flag:

for i in range(0,len(f)):
  f[i]=chr(ord(f[i])+list_080[i])
print ''.join(f)

整體的代碼爲:

import string
g=[27,114,17,118,8,74,126,5,55,124,31,88,104,7,112,7,49,108,4,47,4,105,54,77,127,8,80,12,109,28,127,80,29,96]

f=[]
for i in range(0,len(g)-1):
  found=False
  for tmpf in string.printable:
    if g[i+1]==g[i]+ord(tmpf)-2*(g[i]&ord(tmpf)):
      f.append(tmpf)
      found=True
      break
  if not found:
    print "failed"
    break

list_080=[]
flines=open("f_lines.txt","r")#r,a指令列表
for line in flines:
  list_080.append(-(line.count('r')-line.count('a'))) 
print list_080

for i in range(0,len(f)):
  f[i]=chr(ord(f[i])+list_080[i])
print ''.join(f)

參考地址:https://sh1rker.github.io/2018/09/29/cgctf-homuraVM/

 

480小時精通C++:

elf,導入ida

獲得main函數

發現只是簡單輸出加密後的flag

函數列表中發現:

查看內容:

發現調用了很多函數,查看這些函數,發現內容相同,只是一個數值改變了:

一共480個函數,key的值從001001001到480480480

編寫成python看看:

def encrypt_i(a1,a2,i):
  key=str(i).zfill(3)*3
  v9=key
  v8=len(v9)
  result=""
  for i in range(a2):
    v2=a1[i]
    v3=v2
    v4=v9[i%v8]
    result+=chr(ord(v4)^ord(v3)^i)
  return result

都是xor,逆運算和正運算一樣

逆運算flag:

def encrypt_i(a1,a2,i):
  key=str(i).zfill(3)*3
  v9=key
  v8=len(v9)
  result=""
  for i in range(a2):
    v2=a1[i]
    v3=v2
    v4=v9[i%v8]
    result+=chr(ord(v4)^ord(v3)^i)
  return result

v6 = 'j4Nscadb';
v7 = '[n<g_q`o';
v8 = 'cWv3|waE';
v9 = 'Dt_{q1x[';
v10 = '})wu';
#62646163734e346a6f60715f673c6e5b4561777c337657635b7831717b5f74447577297d
encrypted_flag=v6[::-1]+v7[::-1]+v8[::-1]+v9[::-1]+v10[::-1]#注意加密的flag的輸出順序

for i in range(480,0,-1):
  encrypted_flag=encrypt_i(encrypted_flag,len(encrypted_flag),i)

print encrypted_flag

 

simple machine

elf 導入ida,注意是32位

查看main

需要0x804B100和0x804B060的54長度數組相同

0x804B100 至 0x804b136

0x804B060 至 0x804b096

查看這兩段地址,0x804B100 至 0x804b136是空的,之後應該會把運算結果寫在這裏,0x804B060 至 0x804b096有數據,應該是目標結果

仔細看一下main:

輸入的s加密過程這兩個函數:

先看sub_8048633:

int __cdecl sub_8048633(int a1, unsigned int a2)
{
  unsigned int v2; // eax@3
  int v3; // eax@3

  sub_8048567(dword_804B15C);
  dword_804B15C = dword_804B158;
  sub_8048567(dword_804B150);
  sub_8048567(dword_804B144);
  dword_804B158 -= 48;
  *(_DWORD *)(dword_804B15C - 29) = 'deef';
  *(_DWORD *)(dword_804B15C - 25) = 'daed';
  *(_DWORD *)(dword_804B15C - 21) = 'feeb';
  *(_DWORD *)(dword_804B15C - 17) = 'efac';
  *(_BYTE *)(dword_804B15C - 13) = 0;
  for ( *(_DWORD *)(dword_804B15C - 12) = 0; ; ++*(_DWORD *)(dword_804B15C - 12) )
  {
    dword_804B140 = *(_DWORD *)(dword_804B15C - 12);
    if ( dword_804B140 >= a2 )
      break;
    dword_804B14C = *(_DWORD *)(dword_804B15C - 12);
    dword_804B140 = a1;
    dword_804B150 = dword_804B14C + a1;
    dword_804B14C = *(_DWORD *)(dword_804B15C - 12);
    dword_804B140 = dword_804B14C + a1;
    dword_804B140 = *(_BYTE *)(dword_804B14C + a1);
    byte_804B164 = dword_804B140;
    *(_BYTE *)(dword_804B15C - 41) = dword_804B140;
    dword_804B144 = *(_DWORD *)(dword_804B15C - 12);
    dword_804B158 -= 12;
    dword_804B140 = dword_804B15C - 29;
    sub_8048567(dword_804B15C - 29);
    v2 = strlen(*(const char **)dword_804B158);
    dword_804B158 += 16;
    dword_804B148 = v2;
    dword_804B140 = dword_804B144;
    dword_804B14C = 0;
    sub_80485AB(v2);
    dword_804B140 = dword_804B14C;
    dword_804B140 = *(_BYTE *)(dword_804B14C - 29 + dword_804B15C);
    byte_804B164 = dword_804B140;
    byte_804B164 = *(_BYTE *)(dword_804B15C - 41) ^ dword_804B140;
    *(_BYTE *)dword_804B150 = byte_804B164;
    v3 = dword_804B140;
    LOBYTE(v3) = 0;
    dword_804B140 = v3 + (unsigned __int8)byte_804B164;
  }
  sub_80485A5();
  dword_804B158 = dword_804B15C - 8;
  sub_8048584(&dword_804B144);
  sub_8048584(&dword_804B150);
  return sub_8048584(&dword_804B15C);
}

中間很多冗雜的步驟,很多可以抵消掉,仔細重寫後:

def sub_8048633(a1,a2):
  key="feeddeadbeefcafe"
  for i in range(a2):
    a1[i]=a1[i]^key[i%len(key)]
  return a1

再看sub_80488C7:

void __cdecl sub_80488C7(int a1, int a2, int a3)
{
  sub_8048567(dword_804B15C);
  dword_804B15C = dword_804B158;
  dword_804B158 -= 16;
  for ( *(_DWORD *)(dword_804B15C - 4) = 0; *(_DWORD *)(dword_804B15C - 4) <= 2u; ++*(_DWORD *)(dword_804B15C - 4) )
  {
    for ( *(_DWORD *)(dword_804B15C - 8) = 0; ; ++*(_DWORD *)(dword_804B15C - 8) )
    {
      dword_804B148 = a3;
      dword_804B14C = 1431655766;
      dword_804B140 = a3;
      sub_80485DB(1431655766);
      dword_804B14C -= (unsigned int)dword_804B148 >> 31;
      dword_804B140 = dword_804B14C;
      if ( *(_DWORD *)(dword_804B15C - 8) >= (unsigned int)dword_804B14C )
        break;
      dword_804B148 = a3;
      dword_804B14C = 1431655766;
      dword_804B140 = a3;
      sub_80485DB(1431655766);
      dword_804B14C -= (unsigned int)dword_804B148 >> 31;
      dword_804B140 = dword_804B14C;
      dword_804B140 = dword_804B14C * *(_DWORD *)(dword_804B15C - 4);
      dword_804B14C = dword_804B140;
      dword_804B140 = *(_DWORD *)(dword_804B15C - 8);
      dword_804B140 += dword_804B14C;
      dword_804B14C = dword_804B140;
      dword_804B140 = a2;
      dword_804B148 = dword_804B14C + a2;
      dword_804B14C = *(_DWORD *)(dword_804B15C - 8);
      dword_804B140 = 2 * dword_804B14C;
      dword_804B14C *= 3;
      dword_804B140 = *(_DWORD *)(dword_804B15C - 4);
      dword_804B140 += dword_804B14C;
      dword_804B14C = dword_804B140;
      dword_804B140 += a1;
      dword_804B140 = *(_BYTE *)(a1 + dword_804B14C);
      byte_804B164 = dword_804B140;
      *(_BYTE *)dword_804B148 = dword_804B140;
    }
  }
  sub_80485A5();
}

中間的很多步驟都是可以抵消掉,

其中:

(i*0x55555556)>>32等同於i/3

其他步驟逐漸縮減爲:

def sub_80488C7(a1,a2,a3):
  for i in range(3):
    j=0
    while True:
      if j >= a3/3 - (a3 >> 31):
        break
      a2[j+(a3/3 - (a3 >> 31)) * i] = a1[i+3*j]
      j+=1
  return a2

編寫逆運算函數:

def sub_8048633_re(a1,a2):
  key="feeddeadbeefcafe"
  for i in range(a2):
    a1[i]=a1[i]^ord(key[i%len(key)])
  return a1

def sub_80488C7_re(a1,a2,a3):
  for i in range(3):
    j=0
    while True:
      if j >= a3/3 - (a3 >> 31):
        break
      a1[i+3*j]=a2[j+(a3/3 - (a3 >> 31)) * i]
      j+=1
  return a1

提取0x804B060位置的數據:

import struct

buf=idaapi.get_many_bytes( 0x804B060, 27*2) 

dw=[]
i=0
while i<27*2:
	dw.append((struct.unpack("i", bytearray([buf[i],'\x00','\x00','\x00']))[0]))
	i+=1
print dw

獲得:a2=[0, 3, 9, 58, 5, 14, 2, 22, 15, 31, 18, 86, 59, 11, 81, 80, 57, 0, 9, 31, 80, 4, 20, 87, 59, 18, 7, 60, 28, 58, 21, 5, 11, 8, 6, 1, 4, 18, 22, 57, 5, 11, 80, 87, 9, 18, 10, 39, 19, 23, 14, 2, 85, 24]

 

運行逆運算,獲得flag:

def sub_8048633(a1,a2):
  key="feeddeadbeefcafe"
  for i in range(a2):
    a1[i]=a1[i]^key[i%len(key)]
  return a1

def sub_80488C7(a1,a2,a3):
  for i in range(3):
    j=0
    while True:
      if j >= a3/3 - (a3 >> 31):
        break
      a2[j+(a3/3 - (a3 >> 31)) * i] = a1[i+3*j]
      j+=1
  return a2




def sub_8048633_re(a1,a2):
  key="feeddeadbeefcafe"
  for i in range(a2):
    a1[i]=a1[i]^ord(key[i%len(key)])
  return a1
  
def sub_80488C7_re(a1,a2,a3):
  for i in range(3):
    j=0
    while True:
      if j >= a3/3 - (a3 >> 31):
        break
      a1[i+3*j]=a2[j+(a3/3 - (a3 >> 31)) * i]
      j+=1
  return a1

a2=[0, 3, 9, 58, 5, 14, 2, 22, 15, 31, 18, 86, 59, 11, 81, 80, 57, 0, 9, 31, 80, 4, 20, 87, 59, 18, 7, 60, 28, 58, 21, 5, 11, 8, 6, 1, 4, 18, 22, 57, 5, 11, 80, 87, 9, 18, 10, 39, 19, 23, 14, 2, 85, 24]
a1=[0]*len(a2)
a1=sub_80488C7_re(a1,a2,len(a1))
a1=sub_8048633_re(a1,len(a1))
print ''.join([chr(n) for n in a1])

 

Single

64位elf導入ida

先看sub_40070E函數:

改寫一下:

def sub_40070E(a1):
  if len(a1)>0x51:#81
    return False
  for i in range(len(a1)):
    if a1[i] <= 47 || a1[i] > 57:
      return False
  return True

用來判斷s,s的長度<=81,元素>47並且<=57,爲‘0’到‘9’,

81,且爲0-9,可能是數獨?

 

再看sub_40078B:

改寫下:

def sub_40078B(a1, a2):
  for i in range(len(a1)):
    if a1[i] != 48:
      if !a1[i] || a2[i]:
        return False
      a2[i] = a1[i] - 48;
  return a2

當s中的數字不爲0的時候,如果602080對應位置也不爲0則錯誤,如果602080爲0則將s中的數字寫入a2

數獨的猜想很靠近

再看 sub_400AD4

先看 sub_400833:

改寫下:

def sub_400833(a1):
  s=[0]*24

  for i in range(0,9):
    s=[0]*24
    for j in range(0,9):
      s[a1[9 * i + j]]+=1;
    for k in range(1,10):
      if s[k] != 1:
        return False
  return True

作用是判斷每行是否是9個不同的數字,數獨的猜想基本證實

再看 sub_4008FE:

改寫下:

def sub_4008FE(a1):
  s=[0]*24

  for i in range(0,9):
    s=[0]*24
    for i in range(0,9):
      s[a1[9 * j + i]]+=1;
    for k in range(1,10):
      if s[k] != 1:
        return False
  return True

檢測每列是否是不同數字組成

再看sub_4009C9:

改寫:

def sub_4009C9(a1):
  s=[0]*24

  v6 = 3;
  v7 = 3;
  for i in range(0,9):
    s=[0]*24
    for j in range(v6-3,v6):
      for k in range(v7-3,v7):
        s[a1[9 * j + k]]+=1

    for l in range(1,10):
      if  s[l] != 1 :
        return False

    if v7 == 9:
      v7 = 3;
      v6 += 3;
    else:
      v7 += 3;
  return True

判斷每個3*3的塊是否不同數字組成

 

所以602080爲數獨謎面,s爲數獨的解

提取602080:

import struct

buf=idaapi.get_many_bytes(0x602080, 50*2) 

dw=[]
i=0
while i<50*2:
	dw.append((struct.unpack("i", bytearray([buf[i],'\x00','\x00','\x00']))[0]))
	i+=1
print dw

[0, 3, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 3, 2, 4, 9, 0, 0, 9, 0, 1, 0, 7, 0, 6, 0, 7, 4, 6, 0, 0, 0, 0, 0, 0, 0, 1, 8, 0, 0, 0, 6, 3, 0, 0, 0, 0, 0, 0, 0, 1, 4, 7, 0, 8, 0, 9, 0, 4, 0, 7, 0, 0, 7, 4, 2, 1, 0, 0, 0, 6, 0, 0, 0, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

取前81位排列成數獨:

解數獨後:

計算輸入的string:

puzzle=[0, 3, 0, 6, 0, 0, 0, 0, 0, 
6, 0, 0, 0, 3, 2, 4, 9, 0, 
0, 9, 0, 1, 0, 7, 0, 6, 0, 
7, 4, 6, 0, 0, 0, 0, 0, 0, 
0, 1, 8, 0, 0, 0, 6, 3, 0, 
0, 0, 0, 0, 0, 0, 1, 4, 7, 
0, 8, 0, 9, 0, 4, 0, 7, 0, 
0, 7, 4, 2, 1, 0, 0, 0, 6, 
0, 0, 0, 0, 0, 3, 0, 1, 0,]

ans=[4, 3, 1, 6, 9, 5, 7, 2, 8,
6, 5, 7, 8, 3, 2, 4, 9, 1,
8, 9, 2, 1, 4, 7, 3, 6, 5,
7, 4, 6, 3, 2, 1, 5, 8, 9,
5, 1, 8, 4, 7, 9, 6, 3, 2,
9, 2, 3, 5, 8, 6, 1, 4, 7,
1, 8, 5, 9, 6, 4, 2, 7, 3,
3, 7, 4, 2, 1, 8, 9, 5, 6,
2, 6, 9, 7, 5, 3, 8, 1, 4,]

for i in range(len(puzzle)):
	if puzzle[i]!=0:
		ans[i]=0

print ''.join([str(n) for n in ans])

帶入程序驗證,確認獲得flag

 

 

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