3. Misi kita adalah memberikan arah jalan dari P menuju E. Hal ini dapat dilakukan dengan
algoritma BFS. Buat script untuk melakukannya secara otomatis.
#!/usr/bin/envpython
frompwnimport*
dr=[0,1,0,-1]
dc=[1,0,-1,0]
dd=['R','D','L','U']
defbfs(maze,rowc,colc):
queue=[(rowc,colc,[])]
visited=set()
whilequeue:
r,c,l=queue.pop(0)
visited.add((r,c))
forkinrange(4):
row=r+dr[k]
col=c+dc[k]
ifrow<0orrow>=len(maze):
continue
ifcol<0orcol>=len(maze[0]):
continue
ifmaze[row][col]=='E':
returnl+[dd[k]]
ifmaze[row][col]!='':
continue
if(row,col)invisited:
continue
queue.append((row,col,l+[dd[k]]))
r=remote('62.4.3.98',10111)
printr.recvuntil("start")
r.recvline()
r.sendline("")
while1:
s=r.recvline()
prints
if"flag"ins:
prints
break
s=r.recvline()
s=s.split()
row=int(s[-1].strip())
s=r.recvline()
s=s.split()
col=int(s[-1].strip())
printrow,col
2
4.
maze=[]
foriinrange(row):
s=r.recvline().strip()
maze.append(s)
if'P'ins:
rowc=i
colc=s.index('P')
forcinbfs(maze,rowc,colc):
printr.recvline(),
r.recvline()
r.sendline(c)
s=r.recvline()
if"flag"ins:
prints
break
r.sendline("")
Setelah maze ke-10, didapatkan flag.
Flag: flag{pOwer_pOLe_paPAh}
Reverse
Logang (20 pts)
Diberikan sebuah binary ELF 32-bit yang menggunakan bahasa Go. Langkah pertama dalam
reversing biasanya adalah mencari flag dengan menggunakan command strings dan grep.
$stringslogang|grep-iE"^[a-zA-Z0-9_{}]*$"|less
Terdapat string menarik, yaitu flag{, go_rEverse, dan _aLa_pApah}. Jika digabungkan
akan didapatkan flag.
Flag: flag{go_rEverse_aLa_pApah}
Darwin (100 pts)
Diberikan sebuah binary Mach-O 32 bit. Setelah melakukan decompile dengan IDA Pro,
pseudocode-nya adalah sebagai berikut.
3
5. signedintstart(){
memset(v3,0,0x20u);
printf("Enterthekey:");
v2=0;
fgets(v3,32,__stdinp);
while(v2<32){
v0=0;
if(v3[v2]==10)
v0=-10;
v3[v2++]+=v0;
}
if(sub_1A30(v3))
printf("Congratz,theflag:nflag{yOu_%s_3v3r}n",v3);
else
printf("Wrong%snotthekey.n",v3);
}
Program meminta masukan key, lalu dilakukan pengecekan dengan fungsi sub_1A30. Jika
fungsi bernilai true, maka flag-nya adalah flag{yOu_<key>_3v3r}.
boolsub_1A30(char*a1){
v18=strlen(a1);
v17=0;
v16=0;
v15=0;
v14=0;
v13=0;
v12=0;
for(i=0;i<v18;++i){
if(i%2)
v7=*(a1+i)^v14;
else
v7=v14;
v14=v7;
if(i%2==1)
v6=v13;
else
v6=*(a1+i)^v13;
v13=v6;
if(i%2)
v5=0;
else
v5=*(a1+i);
v17+=v5;
if(i%2==1)
v4=*(a1+i)^v15;
else
v4=v15;
v15=v4;
}
4
7. Terdapat beberapa kondisi yang harus dipenuhi variabel tersebut, yang akan kita sebut
constraint. Permasalahan constraint seperti ini dapat dicari solusinya dengan cepat dengan
menggunakan Z3. Solver script untuk constraint ini adalah sebagai berikut.
#!/usr/bin/envpython3
fromz3import*
importstring
importitertools
length=13
X=[BitVec('x%s'%i,32)foriinrange(length)]
s=Solver()
#charsetconstraint,letters+digits+underscore
foriinrange(len(X)):
s.add(Or(
And(X[i]>=ord('A'),X[i]<=ord('Z')),
And(X[i]>=ord('a'),X[i]<=ord('z')),
And(X[i]>=ord('0'),X[i]<=ord('9')),
X[i]==ord('_')
))
xor_half=X[0]
foriinrange(1,len(X)//2):
xor_half^=X[i]
xor_even=X[0]
add_even=X[0]
xor_odd=X[1]
add_odd=X[1]
foriinrange(2,len(X)):
ifi%2==0:
xor_even^=X[i]
add_even+=X[i]
else:
xor_odd^=X[i]
add_odd+=X[i]
v3=23
foriinrange(len(X)):
v3=(X[i]<<i)+7*v3
v3=v3>>4
s.add(add_even%10==8)
s.add(add_odd%10==add_even%10)
s.add(xor_even^xor_odd==90)
s.add(xor_half==21)
s.add(xor_odd==56)
s.add((add_odd+add_even)/10==116)
6
11.
void__usercallsub_4010B9(inta1@<esi>){
for(i=0;i<25&&(*(byte_405037[i]+a1)^*(byte_405031[i%6]+
a1))==byte_405051[i];++i){
}
}
Fungsi tersebut hanyalah looping yang dalamnya kosong. Akan tetapi, saya menduga fungsi
tersebut melakukan pengecekan apakah input kita sudah benar apa belum, yaitu benar jika
berhasil melakukan looping dari awal sampai akhir.
Pseudocode-nya dapat disederhanakan lagi seperti ini.
filename=GetFileName()
filename=filename[:-(4*(len(filename)%11))]
v_sha256=sha256(filename)
check(v_sha256)
xor=v_sha256^unk_405000
ifmd5(xor)==unk_405021:
flag=xor
else:
nope
Nama file haruslah mempunyai panjang yang jika di-modulus 11 bernilai 1, karena saya
mengasumsikan hal tersebut untuk menghilangkan string “.exe” (panjangnya 4, sehingga -4 *
1 = -4) pada variabel filename. Dengan asumsi tersebut, panjang minimum filename
adalah 12, dengan 4 karakter terakhir adalah “.exe”. Dengan asumsi possible characters adalah
[A-Za-z0-9_]{8}, maka jika dilakukan bruteforce dibutuhkan percobaan sebanyak 63 ** 8
=248155780267521 kali, sehingga tidak feasible dilakukan.
Cara lainnya adalah dengan menggunakan constraint dari fungsi sub_4010B9. Fungsi tersebut
disederhanakan menjadi seperti ini.
defcheck(v_sha256):
foriinrange(25):
ifv_sha256[idx1[i]]^v_sha256[idx2[i%6]]!=check_sha256[i]:
returnFalse
returnTrue
Masalah lainnya adalah setiap byte pada v_sha256 dapat bernilai dari 0x00 hingga 0xFF,
sehingga bruteforce juga tidak feasible. Akan tetapi, jika diperhatikan, nilai variabel xor adalah
flagnya! Sehingga pasti karakter pada xor hanyalah [A-Za-z0-9_{}], dimulai dengan
string flag{, dan diakhiri karakter }. Dengan begitu, key space untuk melakukan bruteforce
10
12. jauh berkurang. Permasalahan constraint seperti ini dapat dicari solusinya dengan Z3. Terakhir,
lakukan pengecekan dengan MD5. Jika salah, cari solusi lain. Jika benar, maka solusi tersebut
sudah tepat. Solver untuk soal ini adalah sebagai berikut.
#!/usr/bin/envpython3
fromz3import*
fromhashlibimportmd5
defmain():
xor_sha=[0x67,0x72,0x9F,0x0C7,0x0B1,0x96,0x72,0x4B,0x19,0x82,
0x35,0x0C,0x0E7,0x0D6,0x0AD,0x0A9,0x9F,0x3D,0x0A6,0x68,0x89,
0x0F6,0x25,0x0A6,0x0A0,0x96,0x8F,0x64,0x0D4,0x56,0x0F4,0x0BE]
md5_flag=[0x9F,0x0A,0x24,0x0BA,0x92,0x85,0x0EB,0x5E,0x0FC,
0x0DB,0x57,0x0C2,0x3A,0x5,0x63,0x0F7]
md5_flag=bytes(md5_flag)
check=[0x0C9,0x0E0,0x0D8,0x9F,0x25,0x0FD,0x0AB,0x99,0x0C8,
0x1E,0x3A,0x0B5,0x5C,0x4C,0x0BB,0x0B,0x1E,0x2D,0x1C,0x3C,0x22,
0x3E,0x0B0,0x0DC,0x0D8]
idx1=[0x13,0x8,0x0E,0x0B,0x18,0x0D,0x1B,0x11,0x5,0x14,0x17,
0x1E,0x19,0x0C,0x1C,0x10,0x9,0x1D,0x1A,0x0F,0x7,0x15,0x0A,0x12,
0x6,0x16]
idx2=[0x2,0x4,0x0,0x3,0x1F,0x1]
s=Solver()
X=[BitVec('x%s'%i,8)foriinrange(32)]
#checker'sconstraints
fori,cinenumerate(check):
i1=idx1[i]
i2=idx2[i%6]
s.add((X[i1]^X[i2])==c)
#charsetconstraints
fori,xinenumerate(X):
x_xor=x^xor_sha[i]
s.add(Or(
And(x_xor>=ord('A'),x_xor<=ord('Z')),
And(x_xor>=ord('a'),x_xor<=ord('z')),
And(x_xor>=ord('0'),x_xor<=ord('9')),
x_xor==ord('_'),
x_xor==ord('{'),
x_xor==ord('}'),
))
#suffixandprefixconstraints
s.add(X[0]^xor_sha[0]==ord('f'))
s.add(X[1]^xor_sha[1]==ord('l'))
s.add(X[2]^xor_sha[2]==ord('a'))
s.add(X[3]^xor_sha[3]==ord('g'))
s.add(X[4]^xor_sha[4]==ord('{'))
s.add(X[-1]^xor_sha[-1]==ord('}'))
11
13.
#exploreallsolutions
whiles.check()==sat:
m=s.model()
sha256=[m.evaluate(x).as_long()forxinX]
flag=[x^xor_sha[i]fori,xinenumerate(sha256)]
#checkmd5
h=md5(bytes(flag))
ifh.digest()==md5_flag:
sha256=''.join([hex(c)[2:].zfill(2)forcinsha256])
flag=''.join([chr(c)forcinflag])
print("SHA256:",sha256)
print("Flag:",flag)
break
#preventsamemodelfornextsolution
s.add(Or([x!=m[x]forxinX]))
if__name__=='__main__':
main()
Didapat SHA-256 untuk filename adalah
011efea0cac926232add733f86e3d9f6ab53c237be9e40f9e6a2e255ba33abc3 yang
jika di-googling merupakan hash dari kata P4ssw0rd. Sehingga jika nama file diganti dari
siapaaku.exe menjadi P4ssw0rd.exe, flag akan ditampilkan.
Flag: flag{_Th3_F3a5t_4nd_7he_F4m1ne_}
12