controlpro

Side Channel Marvel 활용해보기 - Differential Computational Analysis 본문

카테고리 없음

Side Channel Marvel 활용해보기 - Differential Computational Analysis

controlpro 2023. 2. 1. 17:54
728x90

https://github.com/SideChannelMarvels/Tracer 

 

저번에 Pintools 활용하기에서 저게 불편해서 내가 개발한다고 했는데, 일단 저 tool을 어떻게 써는지를 알고 분석을 해야할 것 같아서 이번 포스팅을 시작한다. 

 

나는 주로 Pintools을 이용해서 해당 분석을 진행할 것이므로, Tracer안에 있는 TracerPIN만을 사용할 예정이다. (그나마 pintools이 윈도우에서 동작시키기 좀 편하다.)

 

0. 설치

이 모듈은 Pintools에 저자가 사용한 Tracer.cpp라는 파일을 패치해서 사용하는 것이다. 이 cpp 파일을 사용하기 위해서는 지금 pintools 최신 모듈을 사용하는 것이 아니라 pintools 3.15버전을 사용해야 호환이 되는 것 같다.  딴 것을 많이 다운로드를 해봤는데, 잘 안된다... 그래서 홈페이지에 들어가서 

pin-3.15-98253-gb56e429b1-gcc-linux

아래의 버전을 다운 받고 설치를 하면 잘 된다.

 

1. Differential Computational Analysis

해당 공격은 부채널 분석의 일환으로 기존의 내가 하는 하드웨어의 전력 전자파를 이용한 분석이 아닌 소프트웨어에서 동작하는 암호의 메모리 정보를 이용하여, 부채널 분석을 하는 것이다.

 

사실 이렇게 말하지만 기본적인 부채널 분석과 동일한 것  같다. 자 분석을 시작해보자! (내가 직접 코딩하는 건 아니다..)

 

https://github.com/SideChannelMarvels/Deadpool 

 

GitHub - SideChannelMarvels/Deadpool: Repository of various public white-box cryptographic implementations and their practical a

Repository of various public white-box cryptographic implementations and their practical attacks. - GitHub - SideChannelMarvels/Deadpool: Repository of various public white-box cryptographic implem...

github.com

 

데이터 셋은 여기서 가져와 보자, 해당 Deadpool 데이터 셋들은 White box의 암호의 데이터들을 가지고 분석을 진행한다.

나는 여기서 wbs_aes_openwhitebox_chow 해당 데이터 셋을 이용해보려고 한다. 

a = fopen('mem_data_rw1_200_129280.trace' , 'r');
for i=1:(16160 * 200)
temp = fread(a , 8 , 'uint8');
temp = dec2bin(temp);
temp = temp';
trace1(:,i) = bin2dec(temp);
end
trace1 = reshape(trace1 , [200 , 16160])

1-1. 메모리 수집 정보 위치 잡기

위의 폴더를 들어가게 되면 traces 폴더에 들어가면 위치를 특정할 수 있게 나오게 된다. 

Tracer -t sqlite -- ../target/encryptECB -key ../target/key.txt -in <(echo 000102030405060708090a0b0c0d0e0f|xxd -r -p) -out >(xxd -p)

해당 명령어를 쳐보도록하자 그러면 trace-full-info.sqlite라는 파일이 나오는데 , 이걸 확인해보기 위해서는 tracegraph를 설치해야한다. 이 모듈도 아까 설치하기에서 깔아야한다. 근데, 문제는 이 모듈은 QT등 여러 시각화 도구를 사용하게 되는데, 이게 현재의 버전과 맞지 않아서 compile 자체가 안된다.  그래서 내가 2주동안 혼자서 수정했다. 

 

쨋든 명령어를 쳐서 보게 되면

다음의 도저히 이해할 수 없는 그림이 나온다. 해당 바이너리는 딱 White Box만 실행되는 것이 아니고, White Box가 실행되기 위해서 어려가지 사전 작업을 거치는 것 같다. 실제로 분석을 진행하기 위해서는 White Box에 사용되는 메모리 위치를 정확하게 알아야 한다. 일단 그 부분은 경험적인 측면이 좀 강한 것 같으니까 이사람이 알려준데로 분석을 진행해보자. 

We can see most AES rounds occur somewhere between 0x474b40 and 0x475df6 with the data beyond 0xc820080000 and the stack between 0xc8201cc000 and 0xc8201db000 (with some data being read only).

다음과 같이 써져 있고, 해당 주소를 보면

이렇게 나와있다. 마음의 눈으로 잘보면, 반복되는 구간이 있기 때문에, 해당 명령어 셋들이 WB-AES를 실행하는 부분이라고 추측을 하고 들어간다...

 

이제 이렇게 어떤 주소에 WB-명령어가 있는 지 확인을 한다음에 해당 주소가 접근하는 메모리를 확인하면 된다. 

접근하는 메모리는 0xc8201cc000 and 0xc8201db000 여기 이렇게 확인을 했으면 해당 주소의 파형을 수집해보자. 

 

1-2. 메모리 수집 하기

해당 폴더를 들어가면 trace_it.py가 있다. python파일을 열어보면

#!/usr/bin/env python

import sys
sys.path.insert(0, '../../')
from deadpool_dca import *

def processinput(iblock, blocksize):
    return (None, ["-key ../target/key.txt -in <(echo %0*x|xxd -r -p) -out >(xxd -p)" % (2*blocksize, iblock)])

def processoutput(output, blocksize):
    return int(''.join([x for x in output.split('\n') if len(x)==32][0]), 16)

filters=[Filter('mem_data_rw1', ['R', 'W'], lambda stack_range, addr, size, data: size == 1, lambda addr, size, data: data & 0xFF, '<B')]

#T=TracerGrind('../target/encryptECB', processinput, processoutput, ARCH.amd64, 16, addr_range='0x474b40-0x475df6', filters=filters, shell=True)
T=TracerPIN('../target/encryptECB', processinput, processoutput, ARCH.amd64, 16, addr_range='0x474b40-0x475df6', filters=filters, shell=True)
T.run(200)
bin2daredevil(keywords=filters,
              configs={'attack_sbox':   {'algorithm':'AES', 'position':'LUT/AES_AFTER_SBOX',    'correct_key':'0x693bb79cd7742262c969595c4f8d895f'},
                       'attack_multinv':{'algorithm':'AES', 'position':'LUT/AES_AFTER_MULTINV', 'correct_key':'0x693bb79cd7742262c969595c4f8d895f'}})

다음과 같은 코드가 있는데, 우리가 설치한것은 Valgrind기반의 툴이 아니라 TracerPIN이기 때문에 주석을 바꿔준다음에 python2로 실행해주면 된다. 

 

그러면 다음의 파일이 생성된다.

  • mem_data_rw1_200_129280.trace
  • mem_data_rw1_200_129280.input
  • mem_data_rw1_200_129280.output
  • mem_data_rw1_200_129280.attack_sbox.config
  • mem_data_rw1_200_129280.attack_multinv.config

다음과 같은 파일이 생성된다. 이게 확인해보면, input과 output은 평문과 암호문이라고 생각해보면 되고, trace는 memory 파형이라고 생각하면된다. 원래는 위에 소개 했던 github에 있는 daredevil이라는 툴을 이용하면 분석까지 한번에 끝내주지만, 직접 DCA를 짜보려고 한다. DCA 에 관한 소개는 다음 포스팅을 보도록 하자.

https://c5ntrolpr0.tistory.com/entry/On-the-Ineffectiveness-of-Internal-Encodings-Revisiting-the-DCA-Attack-onWhite-Box-Cryptography

 

On the Ineffectiveness of Internal Encodings -Revisiting the DCA Attack onWhite-Box Cryptography

controlpro On the Ineffectiveness of Internal Encodings -Revisiting the DCA Attack onWhite-Box Cryptography 본문 카테고리 없음 On the Ineffectiveness of Internal Encodings -Revisiting the DCA Attack onWhite-Box Cryptography controlpro 2023. 1. 13.

c5ntrolpr0.tistory.com

 

일단 config 파일 부터 확인해보자. 

[Traces]
files=1
trace_type=i
transpose=true
index=0
nsamples=129280
trace=mem_data_rw1_200_129280.trace 200 129280

[Guesses]
files=1
guess_type=u
transpose=true
guess=mem_data_rw1_200_129280.input 200 16

[General]
threads=8
order=1
return_type=double
algorithm=AES
position=LUT/AES_AFTER_SBOX
round=0
bitnum=all
bytenum=all
correct_key=0x693bb79cd7742262c969595c4f8d895f
memory=4G
top=20

 

다음과 같다. trace 파일이용해서 input으로 분석을 한것 같다.

 

input 파일 부터 분석해보자

다음과 같이 AES에 input되는 16bytes이 써져있다. 문제는 여기서, 

실행 할때는 이렇게 떴으면서, 위는 순서가 다르다는 것이 문제이다. 사실 어떤게 맞는 지는 모르겠으니까, 둘다 실험해보는 것으로 해보자. 

 

trace 파일은 다음과 같다. 

아니 이게 무엇이란 말인가... 온통 0과 1만으로 이루어진 것 같다. config 파일에서는 분명 Sample은 129280이라고 했는데 총 데이터 개수가 1616000이다. 쉣;  처음에는 뭔지는 잘 몰랐으나 일단 대충 예상을 해보건데, 해당 것은 8bit를 잘라서 사용하는 건가.. 

 

흠,, 아무래도 클랐다. 기본 파형의 형태를 모른다면 해결할 수 없다. 

 

 

해결했다. 나이스 .....! 

 

간단하게 생각해서 그냥 0 과 1로 이루어진 파형이라고 생각하면 된다. 그러니까 0 과 1 로 이루어진 파형이고, 해당 파형에서 추측해서 0과 1을 나눠서 공격하면됨. 그래서 일단 파형을 보면 위의 것이고 이를 matlab에서 보면 될 거 같다.

정말 끔찍허다.. 

 

그래서 plaintext와 0~255범위의 key를 추측해서 맞는 값을 찾으면 된다. 

일단 그래서 AES 첫번째 블록인 1번째를 추출한다.

 

이렇게 추출하고,  우리가 부채널 분석에서 추측하는 것은 Sbox (plaintext ^ key) 의 값이니까 그 값으로 만들면된다. (Sbox는 AES sbox 만들었다.)

temp2 = sbox(bitxor(key, block) +1);

그렇게 넣은 temp2를 찾아서 1byte의 특정 자리의 1비트를 추출한다. 나는 MSB로 공격을 시도 했다. 

그래서 0과 1을 개수를 해서 빼주기만 하면~ 

for i=1:256
DPA(:,1) = sum(temp2(:,find(lsb(:,i) == 1)) , 2) / size(find(lsb(:,i) == 1), 1);
DPA(:,2) = sum(temp2(:,find(lsb(:,i) == 0)) , 2) / size(find(lsb(:,i) == 0), 1);
DPAtrace(:,i) = abs(DPA(:,1) - DPA(:,2));
end

이런식으로 코드를 작성가능하고 결과론적으로 DPAtrace를 확인해보면

다음과 같이 나오고 초기 부분에 피크가 뜬것을 확인할 수  있다. 이 값을 find함수를 써서 확인해보면

[row , col ] = find(DPAtrace > 0.46);

106이 나오는 데, matlab이니까 105값이 실제 AES의 첫번째 키가 되는 것이다.

 

 

728x90
반응형