본문 바로가기

CTF/Write-up

0ctf 2015 vezel

요즘 스스로 너무 나태해졌다고 생각해서 문제를 풀어 보기로했다.


우선 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