main 함수를 보면 'enter code: ' 와 'sum is ' 사이에 호출되는 sub_406190 함수로 가보면 입력받은 문자열을 한 글자씩 비교하는 부분을 찾을 수 있다.
이 전에 풀었던 magic이나 alchemy와는 달리 아스키 값을 바로 비교하는 게 아니라 함수안에서 연산을 통해 값을 비교한다.
마지막 if문을 보면 v33이 249이 아니면 실행이 중지되는데, v33은 매개변수로 받았던 문자를 연산한 최종 값이 들어간다.
rdi를 이용해 연산을 하니까 - 부분은 +로 + 부분은 -로 계산하면 어떤 문자인지 알 수 있다.
a1 - 3 + 7 = 10 --> a1 = 3 - 7 + 10
import sys, commands, os
ls=os.listdir('./witchcraft_dist')
ls.sort()
for fname in ls:
command="objdump -d -M intel ./witchcraft_dist/"+fname+" | egrep '(add rdi,0x|sub rdi,0x|cmp rdi,0x)' "
result=commands.getoutput(command).splitlines()
sum=0
print "=========="+fname+"=========="
for disas in result:
try:
num=int(disas[disas.find('x')+1:],16)
except:
continue
if num > 0x7FFFFFFFFFFFFFFF :
num=0xffffffffffffffff-num+1
num=-num
if disas[32]=='a':
sum=sum-num
elif disas[32]=='s':
sum=sum+num
elif disas[32]=='c':
sum=sum+num
sys.stdout.write(chr(sum))
sum=0
print ""
+
원래 disas[32] == 'a'가 아니라 disas.find를 쓰려 했더니 가끔가다가 sub인데 add로 나오는 경우가 있어서 그냥 disas[32]=='a'로 구분했다.
int함수로 16진수 문자열을 정수로 바꾸는데 음수가 제대로 나오진 않아서 따로 연산 추가
'Write Up > CTF' 카테고리의 다른 글
[CTF]encrypt (0) | 2018.01.14 |
---|---|
[CODEGATE2017]HelloProtector (0) | 2018.01.07 |
[CODEGATE2017]RamG (0) | 2018.01.07 |
Defcon CTF 2017 Alchemy (0) | 2017.07.08 |
Defcon CTF 2017 Sorcery (0) | 2017.07.05 |