인스타그램 보고 코틀린 안드로이드 앱 프로그래밍이 있길래 신청했다. 물론 기대는 안했는데 당첨됐다.

 

책이 너무 이쁘다..

 

책을 봤는데 최신버전으로 잘 구성되어있었다. 코틀린에 대한 전반적인 이해하기가 쉬웠고 제트팩, 퍼미션, DB, 다양한 라이브러리, 파이어베이스, FCM 등에 대해 설명이 좋았다.

기본적인 앱 개발 기초부터 시작해서 에제가 정말 많이 있어서 앱 개발 초보자도 읽으면 좋을 거 같다!

 

http://www.yes24.com/Product/Goods/103224662?OzSrank=1 

 

Do it! 깡샘의 안드로이드 앱 프로그래밍 with 코틀린 - YES24

이 책은 구글에서 공식 언어로 채택한 코틀린으로 안드로이드 앱을 개발하는 전 과정을 다룬다. IT 업계의 명강사인 깡샘이 입문자도 쉽게 이해할 수 있게 구성하여 이 책만으로도 코틀린 모바

www.yes24.com

 

'일상' 카테고리의 다른 글

Do it! 깡샘의 안드로이드 앱 프로그래밍 with 코틀린 후기  (0) 2021.09.09
지난 3년 회고  (1) 2021.01.16
2019 POC 컨퍼런스  (0) 2019.11.20

- hosting server : https://fun25.co.kr

- domain : https://hosting.kr

 

우선 서버는 http://sung.pw 를 사용중이다.

 

hosting.kr에서 DNS 세팅

 

fun25에서 1차 도메인과 서브 도메인도 지정해준다. 그래야지 default port를 사용할 수 있다. fun25는 좀 특이하게 내부아이피 이용으로 프락시서버 등록이랑 포트포워딩 자동화해놔서 ssh 접속할 때도 포트를 22가 아니라 외부포트를 지정해서 접속한다 ㅋㅋ;

 

fun25 세팅

 

리버스 프록시로 ctfd는 8000포트를 이용해서 ctf.sung.pw로 서브도메인을 사용하게끔하면 된다.

그리고 CustomLog를 설정할 수 있다. 이게 뭐냐면 ctf.sung.pw에서 발생하는 로그가 /var/log/apache2/access.log 경로에 작성되지 않고 ctf_log/access.log에 로그가 남게된다. 이건 구분할 수 있어서 유용하게 사용할 수 있고 좋은 점 같다.

그래서 $ tail -f /var/log/apache2/access.log로 확인해보면 sung.pw에서 발생하는 로그만 남게된다!

 

a2enmod proxy

a2enmod proxy_http

a2ensite 도메인이름(ex: blog.sung.pw)

systemctl reload apache2.service

 

 

그래서 지금은 구분해서 사용중ㅎㅎ;

 

Reference

https://www.tuwlab.com/ece/5863

https://writingdeveloper.blog/278

'나 보려고 만든거' 카테고리의 다른 글

서브 도메인 설정(Apache2)  (0) 2021.07.21
Docker libc 가져오는법 정리  (0) 2021.07.19
방학동안 해야할거  (4) 2021.06.20
녹스, VMware, WSL2 hyper-v 끄고 키기  (0) 2021.05.20

문제 만들다가 Libc 필요할 때 가져와야되는데 자주 쓸거같아서 정리해둠

앞으론 복붙해야지 크크

 

$ docker-compose up -d --build

$ docker ps -a

$ docker exec -it [CONTAINER ID] /bin/bash (docker attach)

$ apt install -y openssh-client openssh-server (scp 설치를 위해)

$ scp -P 11601 /lib/x86_64-linux-gnu/libc.so.6 root@sung.pw:/root/libc (Docker Container에서 서버로 전송)

32bit : /lib/i386-linux-gnu/libc.so.6

$ scp -P 11601 root@sung.pw:/root/libc/libc.so.6 . (서버에서 현재 디렉토리로 전송)

 

'나 보려고 만든거' 카테고리의 다른 글

서브 도메인 설정(Apache2)  (0) 2021.07.21
Docker libc 가져오는법 정리  (0) 2021.07.19
방학동안 해야할거  (4) 2021.06.20
녹스, VMware, WSL2 hyper-v 끄고 키기  (0) 2021.05.20

- 선린인터넷고 소수전공 시스템해킹 강의준비
- 랩실 일
- Node.js 책 다 보기
- 디지털포렌식챌린지 풀기
- 백준 알골즘 풀기

- Django 공부하기

- 대회 이것저것..

할 수 잇겟지.?

'나 보려고 만든거' 카테고리의 다른 글

서브 도메인 설정(Apache2)  (0) 2021.07.21
Docker libc 가져오는법 정리  (0) 2021.07.19
방학동안 해야할거  (4) 2021.06.20
녹스, VMware, WSL2 hyper-v 끄고 키기  (0) 2021.05.20
  1. ugonfor 2021.08.24 17:28 신고

    그래서 함?

    • 익명 2021.08.24 17:29

      비밀댓글입니다

    • 익명 2021.08.24 17:31

      비밀댓글입니다

    • 익명 2021.08.24 17:31

      비밀댓글입니다

무슨 CTF였더라.. 대충 재밌었던 Level들만 정리 레벨은 아마 1부터15까지 있었나? 명령어도 한정되어서 재밋엇다..

/*
https://del.dog/asm-hell.txt
Command	Description
MOVE A1 A2	A1 is the amount of steps (can be negative), A2 is the direction (0 for vertical, 1 for horizontal)
WAIT A1	A1 is the amount of cycles to wait
UNLOCK A1	A1 is the key
READ M1	M1 stores the result of tile read instruction
ADD M1 A1 A2	M1 stores the result of A1 + A2
SUB M1 A1 A2	M1 stores the result of A1 - A2
MUL M1 A1 A2	M1 stores the result of A1 * A2
JMP A1	A1 line in code to be jumped to
JMPZ A1 A2	jump to line A1 if A2 is zero
JMPN A1 A2	jump to line A1 if A2 is negative
CMP M1 A1 A2	M1 stores the result of A1 > A2 (B); A1 > A2: 1, A1 = A2: 0, A1 < A2: -1
*/

 

Level 8

여기서 주어진 어셈블리 명령에는 div 연산이 존재하지 않아 직접 만들어줘야한다.

왼쪽에 주어진 숫자를 0번 레지스터에 오른쪽에 주어진 숫자를 1번 레지스터에 넣어준다.

0번 레지스터를 계속 1번 레지스터 값으로 빼준 다음에 0번 레지스터에 저장한다. 이렇게 한번 뺄 때마다 5번 레지스터의 값을 1씩 더해준다. 전체적으로 0번 레지스터를 계속 빼주면서 0번 레지스터의 값이 0이 될 때까지 반복해주면 된다.

그리고 키값은 UNLOCK [5]로 카운팅해준 것으로 풀어주면 된다.

 

Level 12

제일 재밌게 푼 문제이다. 소수판별 문제이다. 우선 c언어로 대충 구상하고 풀었다. 아래 c코드를 옮긴 것이 아래와 같다.

for(int i=2; i<n; i++)
   if(n%i==0) MOVE -1 1;
MOVE -1 1;

/*
0 : n
1 : i = 2 
2 : 사용 안함
3 : n-1
4 : cmp [6] [0] 
5 : cmp [1] [3]
6 : n -> 나머지 연산이 구현되어 있지 않아 [1]로 계속 sub해줌 
*/

 

bcdedit /set hypervisorlaunchtype auto 키기 -> WSL2 사용할 때

bcdedit /set hypervisorlaunchtype off 끄기 -> 녹스 사용할 때 

'나 보려고 만든거' 카테고리의 다른 글

서브 도메인 설정(Apache2)  (0) 2021.07.21
Docker libc 가져오는법 정리  (0) 2021.07.19
방학동안 해야할거  (4) 2021.06.20
녹스, VMware, WSL2 hyper-v 끄고 키기  (0) 2021.05.20

대회때 거의 다 했는데 Log.d로 출력하는거 못 봐서 아쉽게 마무리 못했던 문제이다.

Hooking해서 풀어도 되고 아니면 그냥 AES Decrypt 해도 됐다.

문제 풀이 과정은 간단하다. 블루스택이나 녹스를 사용할때 루팅으로 후킹해서 문제를 풀려면 루팅체크하는 부분을 우회해서 후킹을 해야한다. 출제자 풀이를 보면 finish 후킹했는데 나는 라이브러리 후킹해서 풀었다. finish 후킹할 생각을 못해서 조금 시간 뺏겼다. 그 이후로는 쉬움!

 

PS. 문제 풀면서 느낀게 jadx보단 jeb가 훨씬 좋다 ㅇㅇ.. (유료가 최고임)

 

MainActivity

package com.hspace.pengsu;

import android.os.Bundle;
import android.util.Log;
import android.view.View.OnClickListener;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import b.b.c.h;
import b.b.c.u;
import c.b.a.a.a;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Random;

public class MainActivity extends h implements View.OnClickListener {
    public int o;
    public Random p;
    public TextView q;
    public ProgressBar r;
    public ImageButton[] s;
    public RootCheck t;
    public static final int[] u;
    public static int v;

    public static {
        MainActivity.u = new int[]{0x7F0800B7, 0x7F0800B8, 0x7F0800B9, 0x7F0800BA, 0x7F0800BB, 0x7F0800BC, 0x7F0800BD, 0x7F0800BE};  // id:ib1
        MainActivity.v = 0;
    }

    public MainActivity() {
        this.o = 0;
        this.p = new Random();
    }

    @Override  // android.view.View$OnClickListener
    public void onClick(View arg5) {
        int v5 = this.p.nextInt(10);
        this.o = v5;
        int v1 = MainActivity.v + v5;
        MainActivity.v = v1;
        if(v1 == 100) {
            try {
                a.a();
            }
            catch(Exception v5_1) {
                v5_1.printStackTrace();
            }
        }

        if(this.o != 3 && this.o != 5 && this.o != 7 && this.o != 9 && this.o != 10) {
            TextView v5_2 = this.q;
            StringBuilder v0 = c.a.a.a.a.f("Pengsu\'s Wallet : ");
            v0.append(MainActivity.v);
            v0.append("$");
            v5_2.setText(v0.toString());
            this.r.setProgress(MainActivity.v);
            return;
        }

        this.r.setProgress(MainActivity.v);
        MainActivity.v = 0;
        TextView v5_3 = this.q;
        StringBuilder v0_1 = c.a.a.a.a.f("Pengsu\'s Wallet : ");
        v0_1.append(MainActivity.v);
        v0_1.append("$");
        v5_3.setText(v0_1.toString());
    }

    @Override  // b.b.c.h
    public void onCreate(Bundle arg6) {
        super.onCreate(arg6);
        this.s = new ImageButton[8];
        this.setContentView(0x7F0B001C);  // layout:activity_main
        this.q = (TextView)this.findViewById(0x7F0801A0);  // id:wallet
        this.findViewById(0x7F0801A1);  // id:wallet2
        this.r = (ProgressBar)this.findViewById(0x7F080128);  // id:progress
        ((u)this.o()).e.setTitle("Make Pengsu earn 100$");
        this.q.setText("Pengsu\'s Wallet : 0");
        int v0;
        for(v0 = 0; v0 < 8; ++v0) {
            this.s[v0] = (ImageButton)this.findViewById(MainActivity.u[v0]);
            this.s[v0].setOnClickListener(this);
        }

        RootCheck v6 = new RootCheck();
        this.t = v6;
        if(!v6.rootCheck()) {
            StringBuffer v2 = new StringBuffer();
            try {
                Process v6_2 = Runtime.getRuntime().exec("ps adbd");
                v6_2.waitFor();
                BufferedReader v3 = new BufferedReader(new InputStreamReader(v6_2.getInputStream()));
                while(true) {
                    String v6_3 = v3.readLine();
                    if(v6_3 == null) {
                        break;
                    }

                    v2.append(v6_3 + "\n");
                }
            }
            catch(Exception v6_1) {
                v6_1.printStackTrace();
            }

            if(v2.toString().indexOf("bad") != -1) {
                Toast.makeText(this, "No Rooted or ADB Process Detected", 1).show();
                Log.d("MainActivity", "Detection Not Rooted or ADB!");
                return;
            }
        }

        Toast.makeText(this, "Detection Rooted or ADB Process!", 1).show();
        Log.d("MainActivity", String.valueOf(this.t.rootCheck()));
        Log.d("MainActivity", "Detection Rooted or ADB Process!");
        this.finish();
    }
}

 

a

package c.b.a.a;

import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.os.Build.VERSION;
import android.util.Base64;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewParent;
import b.b.h.x0;
import b.h.j.n;
import c.b.a.a.l.d.b;
import c.b.a.a.l.d.c;
import c.b.a.a.l.d.e;
import c.b.a.a.l.d;
import c.b.a.a.v.g;
import c.b.a.a.v.i;
import com.hspace.pengsu.MainActivity;
import com.hspace.pengsu.RootCheck;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.security.MessageDigest;
import java.util.List;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public final class a {
    public static RootCheck a;

    public static void a() {
        a.a = new RootCheck();
        MainActivity v0 = new MainActivity();
        if(a.a.rootCheck()) {
        label_43:
            Log.d("CipherAlgorithm", String.valueOf(a.a.rootCheck()));
            Log.d("CipherAlgorithm", "Please follow the game rules");
            v0.finish();
        }
        else {
            StringBuffer v3 = new StringBuffer();
            try {
                Process v1_1 = Runtime.getRuntime().exec("ps adbd");
                v1_1.waitFor();
                BufferedReader v4 = new BufferedReader(new InputStreamReader(v1_1.getInputStream()));
                while(true) {
                    String v1_2 = v4.readLine();
                    if(v1_2 == null) {
                        break;
                    }

                    v3.append(v1_2 + "\n");
                }
            }
            catch(Exception v1) {
                v1.printStackTrace();
            }

            if(v3.toString().indexOf("bad") == -1) {
                goto label_43;
            }

            Log.d("CipherAlgorithm", "Detection Not Rooted or ADB!");
        }

        String v1_3 = RootCheck.a();
        "hello android world!".getBytes("UTF-8");
        byte[] v0_1 = "hello android world!".getBytes();
        MessageDigest v5 = MessageDigest.getInstance("MD5");
        v5.update("SOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEER".getBytes());
        byte[] v5_1 = v5.digest();
        MessageDigest v6 = MessageDigest.getInstance("SHA-256");
        v6.update(v1_3.getBytes());
        byte[] v6_1 = v6.digest();
        IvParameterSpec v7 = new IvParameterSpec(v5_1);
        SecretKeySpec v5_2 = new SecretKeySpec(v6_1, "AES");
        Cipher v6_2 = Cipher.getInstance("AES/CBC/PKCS5Padding");
        v6_2.init(1, v5_2, v7);
        byte[] v0_2 = v6_2.doFinal(v0_1);
        if(MainActivity.v == 100) {
            Log.d("CipherAlgorithm", " Decrypt Cipher : " + new String(a.d(v1_3, v1_3, Base64.decode("zem8Qf+nUSVM8gsOgKiEeZ+OPRR9EKu76gEjg2eYf4MdXK9wAXrCeTQ9r1CpWcMu".getBytes("UTF-8"), 0)), "UTF-8"));
        }
        else {
            android.os.Process.killProcess(android.os.Process.myPid());
        }

        a.d("SOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEERSOJUBEER", v1_3, v0_2);
    }

    public static Animator b(d arg6, float arg7, float arg8, float arg9) {
        ObjectAnimator v0 = ObjectAnimator.ofObject(arg6, c.a, b.b, new e[]{new e(arg7, arg8, arg9)});
        if(Build.VERSION.SDK_INT >= 21) {
            e v1 = arg6.getRevealInfo();
            if(v1 != null) {
                Animator v6 = ViewAnimationUtils.createCircularReveal(((View)arg6), ((int)arg7), ((int)arg8), v1.c, arg9);
                AnimatorSet v7 = new AnimatorSet();
                v7.playTogether(new Animator[]{v0, v6});
                return v7;
            }

            throw new IllegalStateException("Caller must set a non-null RevealInfo before calling this.");
        }

        return v0;
    }

    public static c.b.a.a.v.d c(int arg1) {
        return arg1 != 0 && arg1 == 1 ? new c.b.a.a.v.e() : new i();
    }

    public static byte[] d(String arg2, String arg3, byte[] arg4) {
        MessageDigest v0 = MessageDigest.getInstance("MD5");
        v0.update(arg2.getBytes());
        byte[] v2 = v0.digest();
        MessageDigest v0_1 = MessageDigest.getInstance("SHA-256");
        v0_1.update(arg3.getBytes());
        byte[] v3 = v0_1.digest();
        IvParameterSpec v0_2 = new IvParameterSpec(v2);
        SecretKeySpec v2_1 = new SecretKeySpec(v3, "AES");
        Cipher v3_1 = Cipher.getInstance("AES/CBC/PKCS5Padding");
        v3_1.init(2, v2_1, v0_2);
        return v3_1.doFinal(arg4);
    }

    public static float e(float arg0, float arg1, float arg2, float arg3) {
        return (float)Math.hypot(((double)(arg2 - arg0)), ((double)(arg3 - arg1)));
    }

    public static int f(Context arg0, int arg1, int arg2) {
        TypedValue v0 = a.r(arg0, arg1);
        return v0 == null ? arg2 : v0.data;
    }

    public static int g(View arg1, int arg2) {
        return a.t(arg1.getContext(), arg2, arg1.getClass().getCanonicalName());
    }

    public static ColorStateList h(Context arg1, TypedArray arg2, int arg3) {
        if(arg2.hasValue(arg3)) {
            int v0 = arg2.getResourceId(arg3, 0);
            if(v0 != 0) {
                ColorStateList v1 = b.b.d.a.a.a(arg1, v0);
                return v1 == null ? arg2.getColorStateList(arg3) : v1;
            }
        }

        return arg2.getColorStateList(arg3);
    }

    public static ColorStateList i(Context arg2, x0 arg3, int arg4) {
        if(arg3.b.hasValue(arg4)) {
            int v0 = arg3.b.getResourceId(arg4, 0);
            if(v0 != 0) {
                ColorStateList v2 = b.b.d.a.a.a(arg2, v0);
                return v2 == null ? arg3.c(arg4) : v2;
            }
        }

        return arg3.c(arg4);
    }

    public static Drawable j(Context arg1, TypedArray arg2, int arg3) {
        if(arg2.hasValue(arg3)) {
            int v0 = arg2.getResourceId(arg3, 0);
            if(v0 != 0) {
                Drawable v1 = b.b.d.a.a.b(arg1, v0);
                return v1 == null ? arg2.getDrawable(arg3) : v1;
            }
        }

        return arg2.getDrawable(arg3);
    }

    public static boolean k(Context arg1) {
        return arg1.getResources().getConfiguration().fontScale >= 1.3f;
    }

    public static boolean l(Context arg1) {
        return arg1.getResources().getConfiguration().fontScale >= 2f;
    }

    public static boolean m(View arg1) {
        return n.m(arg1) == 1;
    }

    public static int n(int arg1, int arg2, float arg3) {
        return b.h.d.a.a(b.h.d.a.c(arg2, Math.round(((float)Color.alpha(arg2)) * arg3)), arg1);
    }

    public static float o(float arg1, float arg2, float arg3) {
        return arg3 * arg2 + (1f - arg3) * arg1;
    }

    public static PorterDuff.Mode p(int arg1, PorterDuff.Mode arg2) {
        if(arg1 != 3) {
            if(arg1 != 5) {
                if(arg1 != 9) {
                    switch(arg1) {
                        case 14: {
                            break;
                        }
                        case 15: {
                            return PorterDuff.Mode.SCREEN;
                        }
                        case 16: {
                            return PorterDuff.Mode.ADD;
                        }
                        default: {
                            return arg2;
                        }
                    }

                    return PorterDuff.Mode.MULTIPLY;
                }

                return PorterDuff.Mode.SRC_ATOP;
            }

            return PorterDuff.Mode.SRC_IN;
        }

        return PorterDuff.Mode.SRC_OVER;
    }

    public static void q(AnimatorSet arg10, List arg11) {
        int v0 = arg11.size();
        long v2 = 0L;
        int v4;
        for(v4 = 0; v4 < v0; ++v4) {
            Animator v5 = (Animator)arg11.get(v4);
            long v6 = v5.getStartDelay();
            v2 = Math.max(v2, v5.getDuration() + v6);
        }

        ValueAnimator v0_1 = ValueAnimator.ofInt(new int[]{0, 0});
        v0_1.setDuration(v2);
        arg11.add(0, v0_1);
        arg10.playTogether(arg11);
    }

    public static TypedValue r(Context arg2, int arg3) {
        TypedValue v0 = new TypedValue();
        return arg2.getTheme().resolveAttribute(arg3, v0, true) ? v0 : null;
    }

    public static boolean s(Context arg1, int arg2, boolean arg3) {
        TypedValue v1 = a.r(arg1, arg2);
        return v1 != null && v1.type == 18 ? v1.data != 0 : arg3;
    }

    public static int t(Context arg3, int arg4, String arg5) {
        TypedValue v0 = a.r(arg3, arg4);
        if(v0 != null) {
            return v0.data;
        }

        throw new IllegalArgumentException(String.format("%1$s requires a value for the %2$s attribute to be set in your app theme. You can either set the attribute in your theme or update your theme to inherit from Theme.MaterialComponents (or a descendant).", arg5, arg3.getResources().getResourceName(arg4)));
    }

    public static void u(View arg2, float arg3) {
        Drawable v2 = arg2.getBackground();
        if((v2 instanceof g)) {
            g v2_1 = (g)v2;
            c.b.a.a.v.g.b v0 = v2_1.b;
            if(v0.o != arg3) {
                v0.o = arg3;
                v2_1.w();
            }
        }
    }

    public static void v(View arg2, g arg3) {
        if(arg3.b.b != null && (arg3.b.b.a)) {
            ViewParent v2 = arg2.getParent();
            float v0 = 0f;
            while((v2 instanceof View)) {
                v0 += n.k(((View)v2));
                v2 = v2.getParent();
            }

            c.b.a.a.v.g.b v2_1 = arg3.b;
            if(v2_1.n != v0) {
                v2_1.n = v0;
                arg3.w();
            }
        }
    }

    public static PorterDuffColorFilter w(Drawable arg1, ColorStateList arg2, PorterDuff.Mode arg3) {
        return arg2 == null || arg3 == null ? null : new PorterDuffColorFilter(arg2.getColorForState(arg1.getState(), 0), arg3);
    }
}

 

RootCheck

package com.hspace.pengsu;

public class RootCheck {
    public static {
        System.loadLibrary("native-lib");
    }

    public static native String a() {
    }

    public native boolean rootCheck() {
    }
}

 

Java_com_hspace_pengsu_RootCheck_rootCheck

__int64 __fastcall Java_com_hspace_pengsu_RootCheck_rootCheck()
{
  unsigned int v0; // ebx

  if ( !access("/sbin/su", 0)
    || !access("/system/su", 0)
    || !access("/system/sbin/su", 0)
    || !access("/system/xbin/su", 0)
    || !access("/data/data/com.example.demoapp.su", 0)
    || !access("/system/app/Superuser.apk", 0)
    || !access("/system/bin/su", 0)
    || !access("/system/bin/.ext/.su", 0)
    || !access("/system/usr/we-need-root/su-backup", 0)
    || (v0 = 0, !access("/system/xbin/mu", 0)) )
  {
    __android_log_print(6LL, "C++", "There is a suspected rooting file.");
    LOBYTE(v0) = 1;
  }
  return v0;
}

 

 

Java_com_hspace_pengsu_RootCheck_a

__int64 __fastcall Java_com_hspace_pengsu_RootCheck_a(__int64 a1)
{
  char *v1; // rbp
  unsigned __int8 v2; // bl
  unsigned __int64 v3; // rdx
  char *v4; // rsi
  char *v5; // rsi
  char *v6; // rsi
  __int64 v7; // rax
  __int64 v8; // rcx
  unsigned __int64 v9; // rdx
  __int64 v10; // rax
  __int64 v11; // rcx
  unsigned __int8 v12; // bl
  char *v13; // r12
  unsigned int v14; // ebp
  __int64 v15; // r14
  __int64 v16; // rax
  int v17; // ebx
  int v18; // ebp
  int v19; // eax
  int v20; // er8
  int v21; // er9
  int v22; // ebx
  __int64 v23; // rbp
  int v24; // eax
  int v25; // er9
  __int64 v26; // rbx
  unsigned __int8 v28; // [rsp+8h] [rbp-A0h] BYREF
  char v29; // [rsp+9h] [rbp-9Fh] BYREF
  unsigned int v30; // [rsp+10h] [rbp-98h]
  void *v31; // [rsp+18h] [rbp-90h]
  __int128 v32; // [rsp+20h] [rbp-88h] BYREF
  void *v33; // [rsp+30h] [rbp-78h]
  __int128 v34; // [rsp+40h] [rbp-68h] BYREF
  void *v35; // [rsp+50h] [rbp-58h]
  __int128 v36; // [rsp+60h] [rbp-48h] BYREF
  void *ptr; // [rsp+70h] [rbp-38h]
  unsigned __int64 v38; // [rsp+78h] [rbp-30h]

  v38 = __readfsqword(0x28u);
  ptr = (void *)operator new(0x20uLL);
  v36 = xmmword_40750;
  strcpy((char *)ptr, "\b!0ASD%/!7!'19-az13FZ9(=(-\"!");
  v35 = (void *)operator new(0x20uLL);
  v34 = xmmword_40720;
  strcpy((char *)v35, "\b$003Z#/AZOQ()*7-az13FZ9(*-\"!");
  v33 = (void *)operator new(0x20uLL);
  v32 = xmmword_40670;
  strcpy((char *)v33, "\b!0c7)%/!7!'16-0=% %-(=(-\"!");
  v1 = (char *)&v32 + 1;
  v2 = 33;
  v3 = 0LL;
  while ( (v2 & 1) == 0 )
  {
    v4 = (char *)&v32 + 1;
    if ( v3 >= v2 >> 1 )
      goto LABEL_12;
LABEL_8:
    v4[v3] ^= 0x44u;
    v5 = (char *)&v36 + 1;
    if ( (v36 & 1) != 0 )
      v5 = (char *)ptr;
    v5[v3] ^= 0x44u;
    v6 = (char *)&v34 + 1;
    if ( (v34 & 1) != 0 )
      v6 = (char *)v35;
    v6[v3++] ^= 0x44u;
    v2 = v32;
  }
  if ( *((_QWORD *)&v32 + 1) > v3 )
  {
    v4 = (char *)v33;
    goto LABEL_8;
  }
LABEL_12:
  v7 = std::__put_character_sequence<char,std::char_traits<char>>(
         &std::cout,
         "standard time starting",
         22LL,
         (char *)&v34 + 1);
  if ( (v32 & 1) != 0 )
  {
    v1 = (char *)v33;
    v9 = *((_QWORD *)&v32 + 1);
  }
  else
  {
    v9 = (unsigned __int64)(unsigned __int8)v32 >> 1;
  }
  v10 = std::__put_character_sequence<char,std::char_traits<char>>(v7, v1, v9, v8);
  std::__put_character_sequence<char,std::char_traits<char>>(v10, "\n", 1LL, v11);
  std::string::basic_string(&v28, &v32);
  v12 = v28;
  v13 = (char *)v31;
  if ( (v28 & 1) != 0 )
    v14 = v30;
  else
    v14 = v28 >> 1;
  v15 = (*(__int64 (__fastcall **)(__int64, _QWORD))(*(_QWORD *)a1 + 1408LL))(a1, v14);
  if ( (v12 & 1) == 0 )
    v13 = &v29;
  (*(void (__fastcall **)(__int64, __int64, _QWORD, _QWORD, char *))(*(_QWORD *)a1 + 1664LL))(a1, v15, 0LL, v14, v13);
  v16 = (*(__int64 (__fastcall **)(__int64, const char *))(*(_QWORD *)a1 + 48LL))(a1, "java/nio/charset/Charset");
  v17 = v16;
  v18 = (*(__int64 (__fastcall **)(__int64, __int64, const char *, const char *))(*(_QWORD *)a1 + 904LL))(
          a1,
          v16,
          "forName",
          "(Ljava/lang/String;)Ljava/nio/charset/Charset;");
  v19 = (*(__int64 (__fastcall **)(__int64, const char *))(*(_QWORD *)a1 + 1336LL))(a1, "UTF-8");
  v22 = _JNIEnv::CallStaticObjectMethod(a1, v17, v18, v19, v20, v21);
  v23 = (*(__int64 (__fastcall **)(__int64, const char *))(*(_QWORD *)a1 + 48LL))(a1, "java/lang/String");
  v24 = (*(__int64 (__fastcall **)(__int64, __int64, const char *, const char *))(*(_QWORD *)a1 + 264LL))(
          a1,
          v23,
          "<init>",
          "([BLjava/nio/charset/Charset;)V");
  v26 = _JNIEnv::NewObject(a1, v23, v24, v15, v22, v25);
  if ( (v28 & 1) != 0 )
  {
    operator delete(v31);
    if ( (v32 & 1) != 0 )
      goto LABEL_27;
LABEL_22:
    if ( (v34 & 1) == 0 )
      goto LABEL_23;
LABEL_28:
    operator delete(v35);
    if ( (v36 & 1) != 0 )
LABEL_24:
      operator delete(ptr);
  }
  else
  {
    if ( (v32 & 1) == 0 )
      goto LABEL_22;
LABEL_27:
    operator delete(v33);
    if ( (v34 & 1) != 0 )
      goto LABEL_28;
LABEL_23:
    if ( (v36 & 1) != 0 )
      goto LABEL_24;
  }
  return v26;
}

 

Exploit code

// com.hspace.pengsu

setTimeout(function(){
	setImmediate(function(){
		Interceptor.attach(Module.findExportByName("libnative-lib.so","Java_com_hspace_pengsu_RootCheck_rootCheck"),{
		    onEnter: function(args){
		        console.log('[*] rooting');
		    },
		    onLeave: function(ret){
		    	console.log(ret);
		    	return 0x0;
		    }
		});

		Java.perform(function(){
			var log = Java.use('android.util.Log');
			log.d.overload('java.lang.String','java.lang.String').implementation = function(a,b){
				console.log('[*]FLAG : ' + a.toString() + ", " + b.toString());
				return this.d(a,b);
			}
		});


		Java.perform(function(){
		    console.warn("[*] 1");
		    var s = Java.use('com.hspace.pengsu.MainActivity');
		    s.v.value = 100;
		    console.log(s.v.value);
		});

		Java.perform(function(){
			var d = Java.use('com.hspace.pengsu.RootCheck');
			d.rootCheck.implementation = function(){
				var retv = this.rootCheck();
				console.log(retv);
				return false;
			}
		});
	});
}, 1000);

 

펭수 귀엽다.

끝!

FLAG : hspace{Vu!lner0able_9an13d0ro6id_1a3p3p1}

 

 

  1. ugonfor 2021.06.23 23:45 신고

    와!

고등학교 진학부터 현재(2021년 1월까지) 내가 경험했던 것들을 적어봤다.

고등학교

중학교 3학년 때부터 형의 도움으로 Java로 프로그래밍을 시작했고 안드로이드 앱 개발하면서 선린인터넷고등학교에 진학했다. 나는 특성화고등학교라는 인식이 안 좋다기 보다는 긍정적으로 봤다. 대학 진학률도 높았고 취업도 잘되며 선후배 관계와 동아리가 정말 잘되어 있었다. 처음에 한국디지털미디어고등학교와 선린인터넷고등학교 둘 중 많은 고민을 했고 결국은 선린을 선택했다. 고등학교 입학까지 담임선생님이 많은 도움을 주셔서 아직도 정말 감사하게 생각하고 있다. 학교 면접볼 때는 첫 면접이라 그런지 정말 많이 떨었다. 면접도 잘 보지 못했지만 합격한 것만으로도 정말 감사했고 마냥 신기했다. 학교에 입학해서 진짜 누구보다 많이 놀았고 뭘 공부해야될지 혼란스럽고 방황했던 시기도 겪었다. 나는 선배들과 친구들의 도움을 받아가면서 해킹, 보안 공부도 시작했다. 단순히 멋져보였고 여러 대회에서 수상하는 모습이 존경스러웠다. 이 때 시작한 공부가 정말 재밌어서 많은 대회도 참여하고 수상하며 다른학교 친구들과도 친해지고 보안하는 사람들과도 많이 알게되면서 좋은 사람들을 많이 알게됐다. 나는 선린인터넷고 다닌걸 후회하지 않고 다시 중학교 때로 돌아간다면 다시 진학할 마음도 있다. 학교 거리가 매일 왕복 2시간씩 통학하는것만 빼면 다 좋았다. 학교 앞에 숙명여대가 있어서 놀거리도 많고 먹을것도 많아서 좋았다. 다들 놀땐 놀고 공부할땐 공부하는 분위기라 정말 최적의 학교였다. 또 외주해서 몇 십만원씩 벌어도 보고 대회 나가서 몇 백만원씩 벌고 했는데 항상 탕진했다 ㅋㅋ 먹고 놀고 옷사고 하면 항상 모자르다.. 일반고에 진학했더라면 경험하지 못할만한 재밌고 소중한 경험들을 한거같다~~<

서울여자대학교 정보보호영재교육원

중학교 3학년 때 고등심화 A 지원해서 떨어지고 고등학교 1학년 때 다시 지원해서 합격했다. 중학교 3학년 때는 아직 실력이 부족한 걸 깨닫고 다시 지원할 때는 완벽히 붙을 정도로 노력했다. 서울여대가 집에서 가까워서 다니기 버겁지는 않았지만 1년동안 격주 주말 오전 9:30 ~ 오후 4:30까지 다니는게 조금 힘들긴 했다. 함께 견학도 가고 2박 3일 집중 교육, 프로젝트, 대회 등등을 했다. 대회에서는 개인전 4등 장려상 단체전 2등으로 한국교육학술정보원장상과 테블릿PC를 받았다. 그 외에도 수료증과 반 1등으로 우수학생으로 상과 50만원도 받았다. 과분하지만 기분은 좋았다.

여기서 좋은 친구들과 선생님들을 만나서 추억도 많이 만들었다. 당시에는 조금 힘들었지만 지금 생각해보면 정말 재밌었다.

영재원 → http://security.swu.ac.kr/giftedu

차세대보안리더양성프로그램 Best Of the Best

고등학교 3학년 6월에 지원해서 취약점분석트랙 교육생으로 합격하여 2021년 1월 현재까지 하고 있다. 약 2~3주 정도 준비해서 합격할 수 있었다. 준비하면서 학교 공부를 조금 놓친 부분이 있기도 하다. 이번년도 경쟁률은 거의 10:1 정도였는데 정말 많은 준비를해서 1차서류와 면접을 걸치며 합격할 수 있어서 정말 좋았다. BoB에 합격하면서 LG Gram 노트북도 제공받고 월마다 30만원정도씩 받으면서 공부를 하고 있다. 1차 교육기간 7월부터는 공통교육부터 시작해서 정말 매일 하루종일 수업을 들었다. 이 당시 코로나로 다 google meet로 수업을 하게됐는데 아쉽게도 오프라인으로 사람들과 함께 듣지 못한다는 점이 아쉬웠다. 8월까지 트랙별로 수업을 하였는데 트랙 수업에서는 심화적으로 배우기 시작했는데 많은 멘토님들이 들려주시는 이야기들과 수업들이 정말 재밌었고 어디가서 쉽게 듣지 못할만한 내용들을 전해들었다. 그리고 Compete도 해야해서 과제도 주어졌다. 이 중 80%의 과제는 해결했는데 어려워서 못한 것도 조금 있었다. 이후 2차로 프로젝트 기간이 있었는데 이 기간이 대입 시기와 겹쳤다. 그래서 솔직하게 많은 도움을 주지 못해서 팀원들에게 죄송했다. 좋은 팀원들과 멘토님들을 만났고 정말 다들 유쾌하시고 좋은 분들이였다. 우리팀은 싸우지도 않고 프로젝트를 해나갔으며 최종적으로는 많은 취약점을 찾아서 제보하며 좋게 끝났다. 그리고 TOP30에는 들지 못했지만 현재는 3차 공통교육을 받고 있다. 해킹이나 보안 공부하는 사람이라면 꼭 해볼만한 프로그램이고 좋은 멘토님들과 형들을 만날 수 있어서 좋은거 같다.

BoB → https://www.kitribob.kr

대회

해킹과 보안에 입문하고 느낀게 알면 알수록 재밌었다. 해킹대회 CTF(Capture The Flag)에 참여하면서 문제를 풀어나가는게 흥미로웠고 고등학교 2학년 때부터 본격적으로 많은 외부 대회에 참여하고 공부하며 많은 대회에서 수상했다. 무작정 대회에 참여하면서 Top-Down 방식으로 공부했다 그래서 앞으로는 기초부터 탄탄하게 공부할 예정이다. 보안 공부하면서 모르는게 있으면 물어볼 선배들과 친구들이 있다는 점이 정말 좋았다. 물어봐도 눈치 보이지 않고 함께 공부하면서 실력도 키울 수 있어서 이보다 좋은 점이 없었다. 마냥 1학년 때는 대회에서 상타고 하는 사람들이 멋있었지만 노력하면 누구든 할 수 있다는 걸 느꼈다. 2학년 때는 Defenit 국내 해킹팀에 들어가서 좋은 사람들도 만나고 대회에 참여하며 국내, 해외 CTF에 많이 참여하며 경험을 쌓을 수 있었다. 국제 대회 참여뿐만 아니라 대회를 직접 운영, 문제 출제를 해보는 경험도 하고 재밌었다. 2021년에는 더 공부해서 팀에 기여할 수 있도록 노력해야겠다. 청소년 대회에서도 많은 수상을 하며 고등학교 2, 3학년동안 정말 알찬 2년을 보냈다. 항상 주변 지인들한테 고맙게 생각한다.

블로그 → http://blog.sung.pw/about/

대학 입시

나는 수시 대부분을 특기자로 넣었다. 숭실대가 가장 먼저 합격자 발표했는데 최초합해서 다른데도 붙을줄 알았는데 다 떨어져서 아쉬운 생각이 든다. 대학 다 떨어지면 취업하려고 마음 먹고 있었다. 수능은 신청했지만 당일날 늦잠자고 환불받았다. 그리고 수험표는 받아놓고 코로나때문에 한번도 안 써봐서 아쉬웠다.

고려대 사이버국방학과(해킹방어특기자) 1차 합격 → 최종 불합격

아주대 사이버보안학과(다산인재 학생부종합) 최종 불합격

과기대 컴퓨터공학과(sw인재전형 학생부종합) 1차 탈락

부산대 정보컴퓨터공학과(sw특기자) 1차 탈락

경희대 컴퓨터공학과(sw특기자) 1차 탈락

숭실대 소프트웨어학부(sw특기자) 1차 합격 → 최초 합격

앞으로

대학교 가기전에 운전면허 따고 영어, 해킹. 알고리즘 등 다른 공부들도 열심히 해놔야겠다. 요즘 너무 공부안하고 놀기만했다 ㅋㅋ 코로나도 좀 줄어들면 좋겠다!

'일상' 카테고리의 다른 글

Do it! 깡샘의 안드로이드 앱 프로그래밍 with 코틀린 후기  (0) 2021.09.09
지난 3년 회고  (1) 2021.01.16
2019 POC 컨퍼런스  (0) 2019.11.20
  1. ugonfor 2021.02.12 16:32 신고

    회고같은 소리하고 있네
    노션 URL만 남길거면 광고좀 지워라 광고사이에 노션 URL이 숨어있다 이자시가!! ㅋㅋㅋㅋㅋㅋ

+ Recent posts