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交易:
在線反編譯:
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