오랜만에 메일함을 들어갔더니 “[신한카드] 임준오님의 01월10일 체크카드 이용대금 명세서입니다.” 이런 제목의 메일이 와있었다. 예전에도 몇번 받아봤는데 첨부파일에 html파일이 있고 생년월일을 입력하면 명세서를 보여주는 형식이었다.
![]() |
메일 화면 |
보안 이메일 명세서라고 나와있는데 얼마나 안전한가 한번 시험해보고 싶은 욕구가 발생했다.
![]() |
생년월일을 받는다. |
![]() |
내 생년월일을 입력하면 정상적으로 열리게 된다. |
이제 소스를 열어보자.
뭔가 난독화가 많이 되어 있다. 일단 beautify 를 해보자.
이제 좀 보인다. 분석을 시작하자!
1. 생년월일을 비교하는 부분을 찾는다.
2. 연산하는 곳을 찾는다.
3. 복호화 코드를 짠다.
이 순으로 분석을 하면 될것 같다.
1. 생년월일을 비교하는 부분을 찾는다.
어떻게 찾을까 생각해봤는데 생년월일이 일치하지 않으면 아래와 같은 alert 창을 띄운다.
저 문자열을 찾아가면 될것 같다.
근데 난독화가 되어있어 alert 함수나 띄우는 문자열을 찾을 수 없었다.
약간의 감을 통해 최상단에 있는 문자열 배열이 함수명이나 메시지들을 담고 있을것 같았다.
엇.. alert가 있다…?
기억을 더듬어 보니 alert가 무려 17개나 있어 문자열로 찾았던 기억이 난다.
그럼 이제 저 지점에 브레이크포인트를 걸고 동적 디버깅을 해보자!
1234를 넣고 상황을 지켜보았다.
1345번째 줄을 보면 _0x9319xd9(함수의 인자) 변수에 내 비밀번호가 들어왔고 1348번째 줄에서 _0x9319xdf함수의 인자로 넘어갔다. 그럼 _0x9319xdf 함수가 복호화하는 함수다 !
2. 연산하는 곳을 찾는다.
1354번째 줄에서 _0x9319xde에 복호화한 값이 들어갔다.
복호화하는 로직을 보니 고정된 키를 사용하는것이 아닌 인풋을 키로 하여 복호화를 진행한다. 복호화 하는 함수를 조금더 분석해보자.
flow: _0x9319xdf -> _0x9319xe2 -> _0x9319xe2
불러오는 함수를 계속 따라가 보면 _0x9319xe4에 “SEED-CBC”란 값을 넣는걸 볼 수 있다.
SEED-CBC를 사용한다고 알려준다. SEED-CBC의 상세한 로직은 이미 쓰고 있는 곳들이 많아 안전할거라 생각하고 따로 분석하지 않았다.
3. 복호화 코드를 짠다.
내가 준 인풋(사용자의 생년월일)을 키로 사용하고 SEED-CBC 블록암호를 사용하기 때문에 복호화 코드를 짜도 의미가 없다. 아니 이미 복호화 해주는 코드는 내장되어 있다. 단지 키를 정의할 수 없을 뿐이다.
키를 구해야 되기 때문에 브루트포싱밖에 답이 없다. 하지만 복호화 하려는 데이터가 너무 크기때문에 1초정도 걸린다.
대충 계산 해보면..
1년을 365로 가정하고 카드 사용자층을 10대 ~ 60대로 선정하면 총 60년을 상대로 브루트포싱해야됨.
그러면 최종적으로 1s * 365 * 60 = 21900s = ~6시간
한개를 복호화 하는데 6시간이나 필요하다. 물론 쓰레딩으로 처리하면 줄일 수 있겠지만 현저히 많은 시간이다.
그러면 과연 더 나은 방법이 없을까?
생각 하던중 정상적으로 복호화 되었는지의 여부를 판별하는 곳을 보았다.
xxx(0, 10) == aaaaa
어.. 복호화된 앞 부분에서 비교를 한다라 .. ?
수 많은 블록을 한 블록으로 줄일 수 있게 되었다.
UNISAFESMAIL_DATA = btoa(atob(UNISAFESMAIL_DATA).substr(0, 16));
한 블록으로 줄인 후 브루트포스 코드를 구현했다.
완성된 브루트포스 코드는 아래와 같다.
function brutePassword() { for (var year=50; year<100; year++) { for (var month=1; month<=12; month++) { var tmp = month+""; if (tmp.length == 1) tmp = "0"+tmp; month = tmp; for (var day=1; day<=31; day++) { var tmp = day+""; if (tmp.length == 1) tmp = "0"+tmp; day = tmp; isSuccess = new UniSafeMail().unisafe_smail_process(year+month+day); if (isSuccess) { console.log(year+month+day); return year+month+day; } } } } }