Skip to content

Instantly share code, notes, and snippets.

@KSHMK
Last active June 25, 2018 12:47
Show Gist options
  • Save KSHMK/96e9390fb3de0e24d234a6ceadf0fd42 to your computer and use it in GitHub Desktop.
Save KSHMK/96e9390fb3de0e24d234a6ceadf0fd42 to your computer and use it in GitHub Desktop.
2018 Whitehat grape Write UP

Grape

분석

해당 파일은 두더지 잡기와 비슷한 게임이다. 한 버튼을 누를 때 마다 점수가 1점식 증가하는 구조였다.

APK 파일은 dex파일을 jar로 바꾸어 분석하는 방법과 apktools를 사용해 smali로 분석하는 방법이 있다. 나는 가장 보기 평한 dex2jar를 사용하였다.

png

dex2jar 변환

png

메인 루팅에서 this.m(게임 스코어)가 각각 500, 1999, 201806점을 넘으면 특정한 문자열을 출력함을 알 수 있다.

png

특히 cs라는 함수는 안드로이드 네이티브 라이브러리 함수였는데 이 함수에 현재 점수를 입력하고 나온 문자열을 출력함을 알 수 있었다.

png

라이브러리 내부에서도 java 코드에서 보앗듯이 점수마다 하는 동작이 다름을 알 수 있다. 이걸 분석하면 풀수 있겠지만 나는 smali 코드 패치를 통해 풀기로 하였다.

패치

png

apktools를 통해 디컴파일을 수행한다. 하지만 리소스에서 오류가 발생할 수 있으므로 리소스 파일은 제외하였다.

패치 부분은 버튼을 눌렀을때 증가하는 점수를 바꾸었다.

png

1 ~ 4 버튼

png

5 ~ 8 버튼

png

9번 버튼

png

apktools로 재빌드 한 뒤, dist 폴더 안의 apk 파일을 SighApk를 사용해 인증서를 넣은뒤 설치하여 나오는 문자열들을 확인하였다.

png

500점 달성시

png

2000점 달성시

png

201806점 달성시

이 힌트들은 apk 내부에 있던 200개의 리시버 중 진짜 리시버를 의미하는 것이였다.

연산

png

7번 리시버를 보면 a.a함수를 호출하는 것을 알 수 있다.

png

a.a 함수는 AES CBC 복호화를 하는 함수인 것을 알 수 있다. 그러면 Broadcast 키는 힌트에 나온 **Kings Never Die!**를 넣으면 되고 암호화된 문자열은

png

strings.xml에 있는 c7 문자열을 사용하면 되었다.

/**
 * Created by Win10 on 2017-11-18.
 */
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class test {
    public static void main(String argv[])
    {
        System.out.println(a.a("i9bjnfNaIew5cZF0cVb5fagP8vWGf/WHjmdmzPJmAXM=","Kings Never Die!"));
        return;

    }
}

class a
{
    public static byte[] a = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

    public static String a(String inp, String key)
    {
        String K = null;
        try {
            byte[] enp = Base64.decode(inp);
            IvParameterSpec localIvParameterSpec = new IvParameterSpec(a);
            SecretKeySpec paramString2 = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
            Cipher localCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            localCipher.init(2, paramString2, localIvParameterSpec);
            K = new String(localCipher.doFinal(enp), "UTF-8");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        }
        return K;
    }
}

FLAG

one summer d@y in june

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment