접속을 해보니 QR코드가 나왔다.

어떠한 정보를 담고 있는듯 한데 하나 하나 맟추는것도 방법이겠다. (어느세월에...???)

개발자도구를 사용해서 소스코드를 분석 해보았다.

보통 웹에서 어떠한 동작이나 이벤트들은 자바스크립트로 작성된 경우가 많다고 한다.

 

/*<![CDATA[*/
 $(function(){ $('#join_img').attr('src',unescape('.%2f%69%6d%67%2f%71%72%2e%70%6e%67'));
  $('#join_img').jqPuzzle({rows:6,cols:6,shuffle:true,numbers:false,control:false,style:{overlap:false}});
  hide_pz();});
 function hide_pz(){
  var pz=$('#join_img div'); if(pz[pz.length-2]){$(pz[1]).remove();$(pz[pz.length-2]).remove();}else{setTimeout("hide_pz()",5);}
 }
/*]]>*/

 

이미지의 id 값을 src로 사용을 하는것 처럼 보이는데 unescape가 뭔지 모르겠다 .

구글링을 하는것도 방법이겠지만 직접 콘솔에 입력을 해보았다.

 

$unescape('.%2f%69%6d%67%2f%71%72%2e%70%6e%67');
"./img/qr.png"

 

이미지를 사용하는것을 확인 할 수 있다.

unescape를 이용해서 QR코드의 정보를 해독하는것 같다.

 

QR 코드(영어: QR code, Quick Response code)은 흑백 격자무늬 패턴으로 정보를 나타내는 매트릭스 형식의 이차원 코드이다. 비슷한 용도로 먼저 사용된 이 차원 코드로는 바코드가 있다. 바코드는 이름 그대로 단순한 막대기 모양의 바를 이차원으로 나열한 것이다 - Wiki pedia

 

Url에 해당 이미지를 입력하면 온전한 QR코드가 나오지 않을까? 

 

 

정상적으로 나오는데 이 QR코드의 내용을 확인 할 수 있다면??

휴대폰으로 찍어도 되지 않을까 -> 사실 이 방법도 있긴한데 안해봤다.

 

온라인 디코더를 이용해서 QR코드를 확인을 했다.

 

 

해당 URL 주소로 이동을 해보니 플래그가 나왔다.

 

성공!!

'CTF > WebHacking' 카테고리의 다른 글

Wargame.kr - fly me to the moon  (0) 2021.02.16
Wargame.kr - WTF_CODE  (0) 2021.02.13
Wargame.kr - login filtering  (0) 2021.02.12
Wargame.kr - flee button  (0) 2021.02.11
Wargame.kr - already got  (0) 2021.02.11

flee button = 도망가는 버튼??

일단 시작을 해보았다.

 

 

버튼을 클릭하기위해서 마우스를 움직여보면 버튼도 같이 움직인다 

결국 클릭을 못하게 해두었다는건데 그래서 개발자도구를 켜서 안의 소스코드를 확인해 보았다.

 

 

버튼의 클릭과 관련된 소스코드를 찾았다.

그래서 이걸 콘솔에서 실행을 시켜주면???

 

window.location='?key=7263';

 

성공

'CTF > WebHacking' 카테고리의 다른 글

Wargame.kr - fly me to the moon  (0) 2021.02.16
Wargame.kr - WTF_CODE  (0) 2021.02.13
Wargame.kr - login filtering  (0) 2021.02.12
Wargame.kr - QR CODE PUZZLE  (0) 2021.02.11
Wargame.kr - already got  (0) 2021.02.11

 

Start 버튼을 클릭해서 시작을 해보니 

 

 

이미 키를 받았다고 한다. (????)

개발자 도구를 사용하기로 했다.

 

 

플래그를 쉽게 확인할 수 있었다.

 

 

성공

'CTF > WebHacking' 카테고리의 다른 글

Wargame.kr - fly me to the moon  (0) 2021.02.16
Wargame.kr - WTF_CODE  (0) 2021.02.13
Wargame.kr - login filtering  (0) 2021.02.12
Wargame.kr - QR CODE PUZZLE  (0) 2021.02.11
Wargame.kr - flee button  (0) 2021.02.11

 

파일을 다운로드해서 실행을 해보면 다른것들과 비슷하게 암호를 입력하는 창이 나온다

문제의 답은 OEP를 구한 후 '등록성공' 으로 가는 분기점의 OPCODE를 구하시오.
정답인증은 OEP + OPCODE

 

 

패킹의 유무를 확인해보았는데 UPX 패킹이 아니라 ASPack 패킹인것 같다 그래서 ASPack이 무엇인지 검색을 해보니

UPX와 같은 패커이다. 새로운 패커가 나왔는데 계속 자동화 패커만 의존할 수 없으니 패킹의 원리가 어떻게 되는지 알아보기로 했다.

 

Packing 원리 

 

저번에 9에서도 비슷한것을 보았지만 PUSHAD로 레지스터 값을 스택에 저장하고 나중에 원본코드가 다 복구되면 메모리에 POPAD 명령을 통해서 다시 레지스터 값을 참조하게 될것이다. 그래서 PUSHAD를 수행한후의 ESP 값에 BP를 설정해주면 쉽게 OEP로 분기가 가능하지 않을까 생각을 해보았다.

 

Break Point

 

레지스터 상태에서도 볼수있듯이 PUSHAD명령을 수행하고 나서 레지스터의 모든 값을 스택에 넣고 시작한다.

 

 

???? : 아무리 찾아도 안나온다 -> 오류가 있는지 확인해보자 

 

 

에러의 내용을 확인해보니 entry point가 다른곳에 있다고하는데 원인을 분석해보면  

1. 패킹이 잘되어 있다.

2. ollydbg가 64bit와 호환이 되지 않는다. -> 둘중에 하나 

패킹은 한마디로 실행 압축을 말한다.

일반 압축파일과 차이점은 일반 파일은 zip으로 확장자가 바뀌지만 패킹은 확장자가 바뀌지 않는다.

  

 

Search for ->Find All commands  

 

 

POPAD를 검색해주면 사용된 모든 POPAD가 나오는데 제일먼저 나온 POPAD안으로 들어가 보았다.

 

 

BP를 걸고 실행을 해보니 바로 실행이 되버려서 (패킹이 여기서 안풀린거 같음)

다시 두번째 POPAD로 들어가보았다.

 

 

 

POPAD 이후로도 실행을 해보았지만 레지스터 값이 변하지 않았다

아마도 지금보는 POPAD이후로 패킹이 풀린듯 하다.

위에서 볼 수 있지만 실행하기전에는 PUSH 0이었다가 실행을 해보면 00445834라고 뜬다.

계속 실행을 시켜보았다.

 

 

return이 나오게 되는데 RETN함수가 실행되면 그 후에 프로그램이 실행된다.

그러면 최근에 적재된 00445834가 OEP 주소인것을 알 수 있다.

 

 

그래서 해당 OEP로 이동을 했다. 

->Follow immediate constant

그럼 이제 성공메세지 확인을 위해서 text string으로 검색을 해보았다.

 

 

well done 이라는 문자열이 성공메세지를 출력해준다는것을 알수있다.

문제에서 말한 OEP는 찾았는데 OPCODE는 무엇인가

 

컴퓨터 과학에서 명령 코드(opcode←operation code, instruction syllable, instruction parcel, opstring[1][2][3][4][5][6][7])는 기계어의 일부이며 수행할 명령어를 나타내는 부호를 말한다. -> Wiki pedia

 

수행할 명령어를 나타내는 부호를 말하는 말한다고 하는데 이 프로그램에서는 조건에 따라서

성공과 실패를 구분하는 지점이 아닌가 생각해보았다.

 

 

JNZ SHORT 0044552B이가 OPCODE인것을 볼 수 있는데 JNZ는 조건 점프라서 zero flag

즉, 두개의 값을 비교했을때 값이 같으면 1이고 다르면 0을 반환 해준다 .

하지만 지금은 zero flag가 0을 반환할것이기 때문에 well done이라는 문자열을 출력하지 않고, 점프도 하지않을것이다.

값이 1이면 0044552B로 점프를해서 well done 이라는 문자열을 보여준다.

 

OEP + OPCODE 이므로 00445834 와 JNZ의 분기점인 75 55가 된다.

 

 

 

 

 

 

'CTF > Reversing' 카테고리의 다른 글

Code Engn Basic RCE Level 12  (0) 2021.05.14
Code Engn Basic RCE Level 11  (0) 2021.05.12
Code Engn Basic RCE level 9  (0) 2021.01.25
Code Engn Basic RCE level 8  (0) 2020.12.04
Code Engn Basic RCE level 7  (0) 2020.12.03

클릭하면 키 파일을 체크한다고 한다.

 

그냥 확인을 해보면 에러메세지를 출력을 하는데 ollydbg로 확인을 해보았다.

 

PUSHAD

PUSHAD라는 명령어를 통해서 레지스터 값을 모두 스택에 적재함을 알 수있다.

패킹의 가능성이 보이기 때문에 패킹의 유무를 확인하고 언패킹을 진행하였다.

upacking
잘못된 언패킹

첫번째 MessageBoxA의 인자 값이 잘못된것을 볼 수 있다.

함수에 전달할 인자가 부족한거 같다. 문제에서 말한 StolenByte와 연관성이 있어보인다.

StolenByte

▶ 패킹된 바이너리를 언패킹할때,  이러한 과정을 방해하기위한 방법으로 프로그램의 일부 바이트를 별도의 영역에서 실행시킴으로써 OEP를 다른 위치로 가장하고 덤프를 쉽게 하지 못하도록 구현한 기법이다. 

올바른 프로그램을 얻기위해서는 StolenByte도 같이 복원해줘야 덤프가 성공적으로 이루어진다.

 

언패킹을 하기전으로 돌아가서 다시 열어보았다.

POPAD

PUSHAD가 레지스터 값을 모두 스택에 적재하는 명령어인데 반대로 스택에서 값을 가져오는 명령어는 POPAD가 아닐까 추측을 해보았다 그리고 POPAD에서 PUSHAD로 스택에 적재된 값들이 PUSH되고 있는것을 확인했다.

 

upx패킹은 코드의 마지막에 있는 JMP명령어를 통해서 원래의 OEP로 가야하는데 원래의 OEP는 0040100C는 OEP가 아니다 원래의 OEP는 00401000이 되어야 한다. 왜냐하면 언패킹을 하고나서 열었을때의 시작주소였기 때문이다.

NOP로 되어있는것으로 해당 부분이 다른 특정 영역에서 실행되고 있음을 알 수 있다.

 

그래서 StolenByte는 POPAD다음에 오는 PUSH 명령어이다.

그리하여 StolenByte는 0040736E의 6A00 과 00407370의 6800204000이다 

따라서 StolenByte는 6A006800204000

노트북이 맛이가서 PC방에서 풀어서 그런가 가독성이 좀 안좋은것 같다.

'CTF > Reversing' 카테고리의 다른 글

Code Engn Basic RCE Level 11  (0) 2021.05.12
Code Engn Basic RCE level 10  (0) 2021.01.28
Code Engn Basic RCE level 8  (0) 2020.12.04
Code Engn Basic RCE level 7  (0) 2020.12.03
Code Engn Basic RCE level 6  (0) 2020.12.02

숫자를 입력받아서 팩토리얼을 구하는 코드 작성 

*팩토리얼 = !로 표기 

ex) 5! = 5x4x3x2x1 = 120 

#include <stdio.h>
#include <stdlib.h>

signed int factorial();
int main(void)
{
    signed int A;
    signed int sum = 1;
    scanf("%d",&A);

    for(int i=1;i<A+1;i++)
    {
        sum *= i;
    }
    printf("%d! = %d",A,sum);
    return 0;
}

'Project > Algorithm' 카테고리의 다른 글

C Basic - 수열의 합  (0) 2021.01.12
C Basic  (0) 2021.01.12

숫자를 입력받고 수열의 합을 구하는 코드를 작성

#include <stdio.h>
#include <stdlib.h>
 
int main(void)
{
    signed int A;
    signed int sum = 0;
    scanf("%d",&A);

    for(int i=1;i<A+1;i++)
    {
        sum += i;
    }
    printf("%d",sum);
    return 0;
}

 

'Project > Algorithm' 카테고리의 다른 글

C Basic - 팩토리얼  (0) 2021.01.12
C Basic  (0) 2021.01.12

1. Semi Colon - 세미콜론 

C언어는 구문이 끝날때 세미콜론을 붙인다.

 

printf("hello world\n");

 

세미콜론을 생략하면 컴파일에러가 발생할 수 있다.  (\n을 사용하면 다음 줄로 넘어간다.)

그러나 여러줄로 되어있지만 내용이 계속 이어지는 문법은 세미콜론을 붙이지 않는다.

 

if (a > 10)
{
    printf("a");
}

for (int i = 0; i < 10; i++)
{
    printf("Hello, world!\n");
}

 

(조건문, 반복문, 함수 등등) -> 추후 자세히 설명하겠다.

세미콜론은 문장의 마침표 역할을 한다.

세미콜론을 붙인다는 것은 구문이 끝났다는것을 명시하는 것이다.

 

2. Comment - 주석 

C언어에서 사람만 알아볼 수 있도록 작성하는 부분을 주석이라고한다.

즉, 주석을 컴파일러가 처리하지 않기 때문에 프로그램의 실행에는 영향을 주지 않는다.

일반적인 경우는 주석을 코드에대한 설명을 표기하거나 특정 코드를 임시로 컴파일되지 않도록 할때 사용한다.

 

//hello world 출력
printf("hello world!\n");

 

//을 사용하면 해당 줄은 모두 다 주석 처리가된다.

아래의 코드에서 hello world 뒤의 printf함수는 동작하지 않는다 (주석이니까)

 

int a = 1+2;//더하기
printf("hello world\n");//printf("123456678765");

 

여러줄을 한번에 주석으로 처리 할 수도 있다.

 

/*
printf("Hello, world!\n");
printf("1234567890");
*/

 

또는 범위 주석으로 한줄에서 한 부분만 주석으로 나타낼 수도 있다.

printf("Hello" /* 안녕하세요 */);

 

3. Brace - 중괄호 

C언어의 문법에서 { } 중괄호를 많이 사용하는데 보통 중괄호는 코드의 범위를 나타낸다.

다음의 코드에서 중괄호로 묶은 부분은 main함수의 범위이다.

 

int main()
{
    printf("Hello, world!\n");

    return 0;
}

 

중괄호는 if , for 등의 키워드가 영향을 미치는 영역애도 사용한다.

 

if (a > 10)
{
    printf("a");
}

for (int i = 0; i < 10; i++)
{
    printf("Hello, world!\n");
}

 

아니면 Struct (구조체)를 정의할때도 사용한다.

 

struct Hello {
    int a;
    int b;
};

 

int main()
{ // 줄의 시작 부분에서 중괄호 사용(1번 스타일)

}

int main() { // 줄의 맨 마지막에서 중괄호 사용(2번 스타일)

}

 

어느것을 사용하던지 상관 없다. 

 

 

4. Indentation - 들여쓰기 

소스 코드를 작성하다 보면 키워드에 따라서 들여쓰기를 하는 경우가 많다.

보통 { (여는 중괄호)가 시작될 때 들여쓰기를 한다.

 

 

들여쓰기를 하지 않더라도 컴파일 에러는 발생하지 않지만, 코드를 쉽게 알아볼 수 있어야 하므로 들여쓰기는 필수이다.

항상 적절한 들여쓰기를 하는 습관을 가지는것이 좋다.

다음과 같이 들여쓰기 방법은 공백(스페이스) 2칸, 4칸, 탭(tab) 등 여러 가지 방법이 있다.

 

 

C 언어에서는 들여쓰기 방법이 문법으로 정해져 있지 않다.

하지만 다른 사람이 만든 소스 코드를 수정할 때는 기존의 들여쓰기 규칙을 따르는 것이 좋다.

일반적으로는 들여쓰기를 공백 4칸으로 사용한다.

'Project > Algorithm' 카테고리의 다른 글

C Basic - 팩토리얼  (0) 2021.01.12
C Basic - 수열의 합  (0) 2021.01.12

기본적인 계산기 프로그램인것 같다.

하지만 문제에서 OEP를 찾으라고 했다.

그래서 일단 OllyDBG로 열기 전에 패킹의 유무를 확인해보았다.

UPX로 패킹이 되어있는것을 확인하고 언패킹을 진행해보았다.

용량이 늘어난것으로 보아 언패킹이 진행된것을 알 수 있다.

그 다음 Olly DBG로 열어보았다.

 

01012475의 주소가 OEP이다 

OEP : 패킹된 파일의 실제 프로그램 시작 부분 

'CTF > Reversing' 카테고리의 다른 글

Code Engn Basic RCE level 10  (0) 2021.01.28
Code Engn Basic RCE level 9  (0) 2021.01.25
Code Engn Basic RCE level 7  (0) 2020.12.03
Code Engn Basic RCE level 6  (0) 2020.12.02
Code Engn Basic RCE level 5  (0) 2020.08.16

첫번째로 패킹의 유무를 확인 해보았다.

보아하니 패킹이 되어있지는 않은것 같다. 

문제에서 하드디스크의 이름을 CodeEngn으로 바꾸면 나오는 시리얼값을 입력하라고 하였다.

그래서 하드디스크의 이름을 관리자 권한으로 변경해주었다.

그리고 나서 Olly DBG로 실행을 해보았다.

패킹이 되어 있지 않아서 시리얼 값을 비교하는 함수가 있을것이라고 추측을 해보았다

IstrcmpiA 함수가 있었다. 이 함수가 서로서로 시리얼 값을 비교해서 성공과 에러 메세지를 띄어주는 곳으로 점프 시키는것 같다. 

함수의 위치로 이동해보았다.

4562-ABEX가 아직 무엇인지는 모르겠으나, 밑의 주소에 CodeEngn이라는 문자열을 PUSH하고 있다.

아마도 하드디스크의 이름을 바꿨을때 이곳으로 PUSH 되는것 같다.

계속 실행을 해보았다.

기존의 CodeEngn 문자열에 4562-ABEX 문자열이 뒤에 추가되었다. 아마 이런식으로 시리얼 값이 정해지는것 같다.

게속 실행해보았다.

 

Code라는 문자가 1글자씩 뒤로 밀리는것을 볼수있는데, 분기가 2번도는것을 보아 2글자씩 뒤로 밀리는것 같다 

그래서 CodeEngn -> EqfgEngn으로 2글자가 밀려서 시리얼값이 생성된다.

L2C-5781이라는 새로운 문자열이 또 보인다 아직은 잘모르겠지만 게속 실행해보았다.

새로 시리얼 값이 생성된것을 볼 수 있다. 

아까 2글자씩 밀렸던 EqfgEngn4562-ABEX의 앞에 L2C-5781이라는 문자열이 추가되었다 

따라서 07.exe의 Serial 값은 L2C-5781EqfgEngn4562-ABEX인것을 알 수있다.

그래서 입력을 해보았다.

성공 메세지가 출력되는것을 확인할 수 있다.

그리고 하드디스크 이름은 원래대로 해주었다.

'CTF > Reversing' 카테고리의 다른 글

Code Engn Basic RCE level 9  (0) 2021.01.25
Code Engn Basic RCE level 8  (0) 2020.12.04
Code Engn Basic RCE level 6  (0) 2020.12.02
Code Engn Basic RCE level 5  (0) 2020.08.16
Code Engn Basic RCE level4  (0) 2020.08.16

+ Recent posts