요즘 스스로 너무 나태해졌다고 생각해서 문제를 풀어 보기로했다.
우선 vezel.apk가 주어지는데 해당 클래스를 보면 MainActivtiy말고는 보이지 않는다.
핵심부분은 여긴데 패키지이름("com.ctf.vezel")을 인자로 getsig를 함수를 실행하고
getCrc 함수의 결과와 합쳐서 최종적으로 0CTF{~~~~~~}를 만들게 되는데
내가 입력한 값이랑 이 값이 같아야한다.
처음엔 바보같이 다른함수를 보지않고 저부분에 0CTF{first+getCrc}를 출력해주도록 스말리 코드를 수정해봤다.
수정 후 아무거나 입력해도 값이 나오는걸 확인할 수 있다.
하지만 성공적으로 패치를 했는데 답이 아니였고 소스를 자세히 봐봤다.
getsig는 패키지 이름으로 시그니쳐값을 구해온 후 hashcode로 바꿔주는것이고
getCrc는 classes.dex의 crc32를 알아오는 것이다.
지금 같은 경우는 수정으로인해 값들이 다 바뀐상태라 당연히 다를 수 밖에 없다.
getcrc는 그냥 classes.dex의 값을 보면 끝이다.
하지만 시그니쳐는 내가 지금 안드로이드 스튜디오가 안깔려있기때문에 확인을 할수가 없었고
안드로이드 안쓰고 값을 알아 낼 수 없을까 하다가 검색을 통해 좋은 글을 하나 발견했다.
들어가보면
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | import java.io.IOException; import java.io.InputStream; import java.lang.ref.WeakReference; import java.security.Signature; import java.security.cert.*; import java.util.Enumeration; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.logging.Level; import java.util.logging.Logger; public class Main { private static final Object mSync = new Object(); private static WeakReference<byte[]> mReadBuffer; public static void main(String[] args) { if (args.length < 1) { System.out.println("Usage: java -jar GetAndroidSig.jar <apk/jar>"); System.exit(-1); } System.out.println(args[0]); String mArchiveSourcePath = args[0]; WeakReference<byte[]> readBufferRef; byte[] readBuffer = null; synchronized (mSync) { readBufferRef = mReadBuffer; if (readBufferRef != null) { mReadBuffer = null; readBuffer = readBufferRef.get(); } if (readBuffer == null) { readBuffer = new byte[8192]; readBufferRef = new WeakReference<byte[]>(readBuffer); } } try { JarFile jarFile = new JarFile(mArchiveSourcePath); java.security.cert.Certificate[] certs = null; Enumeration entries = jarFile.entries(); while (entries.hasMoreElements()) { JarEntry je = (JarEntry) entries.nextElement(); if (je.isDirectory()) { continue; } if (je.getName().startsWith("META-INF/")) { continue; } java.security.cert.Certificate[] localCerts = loadCertificates(jarFile, je, readBuffer); if (false) { System.out.println("File " + mArchiveSourcePath + " entry " + je.getName() + ": certs=" + certs + " (" + (certs != null ? certs.length : 0) + ")"); } if (localCerts == null) { System.err.println("Package has no certificates at entry " + je.getName() + "; ignoring!"); jarFile.close(); return; } else if (certs == null) { certs = localCerts; } else { // Ensure all certificates match. for (int i = 0; i < certs.length; i++) { boolean found = false; for (int j = 0; j < localCerts.length; j++) { if (certs[i] != null && certs[i].equals(localCerts[j])) { found = true; break; } } if (!found || certs.length != localCerts.length) { System.err.println("Package has mismatched certificates at entry " + je.getName() + "; ignoring!"); jarFile.close(); return; // false } } } } jarFile.close(); synchronized (mSync) { mReadBuffer = readBufferRef; } if (certs != null && certs.length > 0) { final int N = certs.length; for (int i = 0; i < N; i++) { String charSig = new String(toChars(certs[i].getEncoded())); System.out.println("Cert#: " + i + " Type:" + certs[i].getType() + "\nPublic key: " + certs[i].getPublicKey() + "\nHash code: " + certs[i].hashCode() + " / 0x" + Integer.toHexString(certs[i].hashCode()) + "\nTo char: " + charSig); } } else { System.err.println("Package has no certificates; ignoring!"); return; } } catch (CertificateEncodingException ex) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException e) { System.err.println("Exception reading " + mArchiveSourcePath + "\n" + e); return; } catch (RuntimeException e) { System.err.println("Exception reading " + mArchiveSourcePath + "\n" + e); return; } } private static char[] toChars(byte[] mSignature) { byte[] sig = mSignature; final int N = sig.length; final int N2 = N*2; char[] text = new char[N2]; for (int j=0; j<N; j++) { byte v = sig[j]; int d = (v>>4)&0xf; text[j*2] = (char)(d >= 10 ? ('a' + d - 10) : ('0' + d)); d = v&0xf; text[j*2+1] = (char)(d >= 10 ? ('a' + d - 10) : ('0' + d)); } return text; } private static java.security.cert.Certificate[] loadCertificates(JarFile jarFile, JarEntry je, byte[] readBuffer) { try { // We must read the stream for the JarEntry to retrieve // its certificates. InputStream is = jarFile.getInputStream(je); while (is.read(readBuffer, 0, readBuffer.length) != -1) { // not using } is.close(); return (java.security.cert.Certificate[]) (je != null ? je.getCertificates() : null); } catch (IOException e) { System.err.println("Exception reading " + je.getName() + " in " + jarFile.getName() + ": " + e); } return null; } } | cs |
위와 같은 소스코드가 있는데
여기부분을 hashcode만 출력하도록 수정하고
이렇게 알아낼 수 가 있었다.
성공!!
'CTF > Write-up' 카테고리의 다른 글
2014 su-ctf commercial_application (1) | 2017.07.01 |
---|---|
TrendMicroCTF - VirusClicker (1) | 2017.06.30 |
hust 2017 참가 후기 & 풀이 (1) | 2017.05.28 |
defcon 2017 (0) | 2017.05.01 |
TAMU CTF reversing (0) | 2017.04.20 |