var net = require('net');

flag='fake_flag';

var server = net.createServer(function(socket) {
    socket.on('data', (data) => { 
        //m = data.toString().replace(/[\n\r]*$/, '');
        ok = true;
        arr = data.toString().split(' ');
        arr = arr.map(Number);
        if (arr.length != 5) 
            ok = false;
        arr1 = arr.slice(0);
        arr1.sort();
        for (var i=0; i<4; i++)
            if (arr1[i+1] == arr1[i] || arr[i] < 0 || arr1[i+1] > 127)
                ok = false;
        arr2 = []
        for (var i=0; i<4; i++)
            arr2.push(arr1[i] + arr1[i+1]);
        val = 0;
        for (var i=0; i<4; i++)
            val = val * 0x100 + arr2[i];
        if (val != 0x23332333)
            ok = false;
        if (ok)
            socket.write(flag+'\n');
        else
            socket.write('nope\n');
    });
    //socket.write('Echo server\r\n');
    //socket.pipe(socket);
});

HOST = '0.0.0.0'
PORT = 23333

server.listen(PORT, HOST);

[그림1] 문제 전체 소스코드



[그림1] 문제의 전체 소스코드를 살펴보면 var형 변수를 쓰는 것과 nodejs에서의 TCP 소켓을 구현하는 방식임을 보고 미루어 보았을 때 nodejs로 구현된 TCP 소켓 서버임을 알 수 있다. 유저가 보낸 data를 받아와 ' '(공백)을 기준으로 split 한 후 배열에 넣어 여러 검증과정과 처리과정을 거친 후 나오는 결과값이 '0x23332333' 인지 확인한 후 맞다면 플래그를 띄운다.



        arr = data.toString().split(' ');
        arr = arr.map(Number);
        if (arr.length != 5) 
            ok = false;
        arr1 = arr.slice(0);
        arr1.sort();

[그림2] 데이터 초기 처리과정




[그림3] Javascript 에서의 split(), map(), slice(), sort() 동작 과정


[그림2]의 초기 데이터 처리과정은 [그림3]과 같이 진행된다. 여기서 주의해야 할 점은 유저의 데이터가 ' data.toString().split(' ') ' 을 통해 'String' 으로 형변환이 되며 arr 배열로 들어가기 때문에 뒤의 ' arr1.sort() ' 코드에서 정렬할 때 'int' 형이 아닌 'string' 형으로 정렬이 된다. 이 말은 곧, 숫자의 크기와 상관 없이 맨 앞글자부터 크기를 비교하기 때문에, [그림3]과 같이 [8, 21, 4, 57, 6]이 배열에 들어갔다면 [21, 4, 57, 6, 8]로 정렬이 되는 것이다. 저는 이걸 헷갈려서 한참을 헤맸다는...



if (arr.length != 5) ok = false; ... for (var i=0; i<4; i++) if (arr1[i+1] == arr1[i] || arr[i] < 0 || arr1[i+1] > 127) ok = false;

[그림4] 유저의 input data 검증 과정


이후 [그림4]와 같이 배열의 크기가 5가 아니면 ok 플래그 변수에 false를 넣고(유저의 인풋값이 스페이스를 기준으로 나누어 5개의 값만을 넣어야 한다), 인풋값 중 같은 값이 있는 지, 혹은 0보다 작거나 127보다 큰 수가 있는 지를 검사한다(sort() 이후 검증을 하기 때문에 arr1[i+1]==arr1[i] 만으로도 같은 값이 있는 지 검사할 수 있다).



        arr2 = []
        for (var i=0; i<4; i++)
            arr2.push(arr1[i] + arr1[i+1]);
        val = 0;
        for (var i=0; i<4; i++)
            val = val * 0x100 + arr2[i];
        if (val != 0x23332333)
            ok = false;
        if (ok)
            socket.write(flag+'\n');
        else
            socket.write('nope\n');

[그림5] 데이터 처리 및 계산, 인증 과정


검증 후 arr2 배열을 새로 만들어 arr2에 arr1의 원소를 앞에서부터 두개씩 더하여 넣는다(총 4개의 원소 발생). 이 arr2 배열에 초기값이 0인 상태로 0x100씩 곱하여 원소를 더하고 이를 다시 이용하고 반복하며 이 과정이 끝났을 때 '0x23332333' 이 맞는 지 검사하고 맞다면 플래그를 띄워준다.




for a in range(0, 124): for b in range(a+1, 125): for c in range(b+1, 126): for d in range(c+1, 127): for e in range(d+1, 128): arr1 = [] arr1.append(str(a)) arr1.append(str(b)) arr1.append(str(c)) arr1.append(str(d)) arr1.append(str(e)) arr1.sort() arr2 =[] arr2.append(str(int(arr1[0])+int(arr1[1]))) arr2.append(str(int(arr1[1])+int(arr1[2]))) arr2.append(str(int(arr1[2])+int(arr1[3]))) arr2.append(str(int(arr1[3])+int(arr1[4]))) val = 0 for x in range (0, 4): val = val * 0x100 + int(arr2[x]) if(val==590553907): break if(val==590553907): break if(val==590553907): break if(val==590553907): break if(val==590553907): break else: print ("[%s] I'm doing.." % str(a+1)) print ("[*] I Found It!!!") print (a, b, c, d, e) print (arr2) print (val)

[그림6] 문제 조건에 부합하는 배열을 찾기 위한 Python 스크립트



문제 코드에서 나타난 과정을 Python으로 똑같이 구현하여 조건에 부합하는 배열을 찾아낸다. 같은 수가 나오면 안되므로 맨 뒤부터 순차적으로 숫자를 증가시키며 값을 찾아낸다.



[그림7] Python 스크립트 실행 결과




[그림8] 인증 결과


Flag Get!!!

'CTF > *ctf (star ctf - xctf) 2018' 카테고리의 다른 글

[Web] 2018 starctf - simpleweb  (0) 2018.04.23

이름 : 유재욱


닉네임 : ar9ang3


학력 : 가천대학교 컴퓨터공학과 학사


소속

 - 라온시큐어 화이트햇 프로젝트팀 전임연구원 (2018. 04. ~ 2019. 08.)

 - 가천대학교 정보보호 동아리 Pay1oad 설립 및 운영 (2018. 03. ~ 2019. 02)

 - KITRI 차세대 보안리더 양성 프로그램 BoB(Best of the Best) 6기 컨설팅 트랙 수료 (2017. 07 ~ 2018. 04)

 - 가천대학교 글로벌캠퍼스 전산정보원 조교 근무 (2017.03 ~ 2017. 06)

 - AhnLab 소프트웨어 QA 모바일 팀 연수생 (2016. 08 ~ 2017. 02)

 - 대학 정보보호동아리 연합 커뮤니티 SUA(SecurityPlus Union Academy) 운영진 및 서경지부장 (2015. 11 ~ 2017. 06)

 - 청와대 대통령경호실 정보작전병 (2014. 10 ~ 2015. 11)


관심분야

 - Security Consulting, Mobile(Android) Reversing, Web Hacking, System Hacking, Bug Hunting, Finance Security


대외발표

 - 2018. 11. KUCIS 영남권 컨퍼런스 발표 - 'Solidity 기반 스마트 컨트랙트 취약점 분석 방법'

 - 2018. 07. CodeEngn 2018 컨퍼런스 발표 - '안드로이드 앱 보안솔루션을 간단히 무력화 할 수 있다고?'

 - 2018. 04. Codegate 2018 컨퍼런스 발표 - '안드로이드 간편결제 앱 취약점 분석을 통한 앱 보안성 향상 연구'

 - 2017. 12. LG유플러스 모의해킹 결과 리포팅 발표 (BoB)

 - 2017. 12. LG전자 서비스 취약점 분석 결과 리포팅 발표 (BoB)


대외실적

 + 한국인터넷진흥원(KISA) S/W 취약점 제보 33회, 2019년 1/4분기 KISA 버그바운티 명예의전당 등록

 + 네이버(NHN) 버그바운티 웹 취약점 제보 18회, Hall of Fame 등록[각주:1]

 + 리디북스(Ridibooks) 버그바운티 웹 취약점 제보 X회, 명예의 전당 등록[각주:2]

 - 2018. 12. 한국정보보호학회 동계학술대회 우수논문상 수상 (Mifare Classic 태그 타입 사용 출입 통제 시스템의 보안 취약점 및 대응방안에 대한 연구)

 - 2018. 08. [KCI 등재] 한국정보보호학회 논문지 투고 - '안드로이드 간편결제 애플리케이션 보안 솔루션 결과값 변조를 통한 검증기능 우회 방법에 대한 연구'

 - 2018. 04. KITRI 차세대 보안리더 양성 프로그램 BoB(Best of the Best) 6기 Best 10 (과학기술정보통신부 장관상)

 - 2018. 04. KITRI 차세대 보안리더 양성 프로그램 BoB(Best of the Best) 6기 Grand Prix 팀 선정(Team. JGG)

 - 2017. 12. 금융보안원 보안 취약점 제보 인증서 수여

 - 2017. 12. 스틸리언(Stealien) 보안 취약점 탐지 인증서 수여

 - 2017. 12. LG유플러스 보안 취약점 탐지 특별상 수여 (IT전략본부장, 000상무)

 - 2017. 04. Codegate 2017 해킹시연영상 공모전 특별상 수상


Email 

 - Personal : jaewook376@naver.com

  1. https://bugbounty.naver.com/ko/halloffame [본문으로]
  2. https://ridi.dev/hall-of-fame [본문으로]

'Profile > Profile' 카테고리의 다른 글

Profile  (2) 2018.04.23
  1. krrr 2019.03.02 17:09 신고

    너무 멋집니다. 어떻게 하면 이런 실적을 쌓을 수 있을까요? 조언 한마디 부탁드립니다.

+ Recent posts