YPrefer's Develop&Security :: YPrefer's Develop&Security

블로그 시작하고, 스킨을 이것저것 바꾸는데 그때마다 적용하기도 귀찮은데

다른 블로그를 참조해야 되는건 더 귀찮아서 정리해봄.

 

링크 : http://alexgorbatchev.com/SyntaxHighlighter/

0. 위 링크에서 최신버전의 syntaxhighlighter를 다운받아 압축해제

 

1. scripts와 styles 폴더 안의 파일을 Tistory 관리자메뉴의 꾸미기>HTML/CSS편집>업로드를 통해 업로드

2. HTML 탭에서 아래 내용 적용

 <head>태그위에 js와 css 넣기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script type="text/javascript" src="./images/shCore.js"></script>
<script type="text/javascript" src="./images/shLegacy.js"></script>
<script type="text/javascript" src="./images/shBrushBash.js"></script>
<script type="text/javascript" src="./images/shBrushCpp.js"></script>
<script type="text/javascript" src="./images/shBrushCSharp.js"></script>
<script type="text/javascript" src="./images/shBrushCss.js"></script>
<script type="text/javascript" src="./images/shBrushDelphi.js"></script>
<script type="text/javascript" src="./images/shBrushDiff.js"></script>
<script type="text/javascript" src="./images/shBrushGroovy.js"></script>
<script type="text/javascript" src="./images/shBrushJava.js"></script>
<script type="text/javascript" src="./images/shBrushJScript.js"></script>
<script type="text/javascript" src="./images/shBrushPhp.js"></script>
<script type="text/javascript" src="./images/shBrushPlain.js"></script>
<script type="text/javascript" src="./images/shBrushPython.js"></script>
<script type="text/javascript" src="./images/shBrushRuby.js"></script>
<script type="text/javascript" src="./images/shBrushScala.js"></script>
<script type="text/javascript" src="./images/shBrushSql.js"></script>
<script type="text/javascript" src="./images/shBrushVb.js"></script>
<script type="text/javascript" src="./images/shBrushXml.js"></script>
<link type="text/css" rel="stylesheet" href="./images/shCore.css">
<link type="text/css" rel="stylesheet" href="./images/shThemeDefault.css">
<script type="text/javascript">
SyntaxHighlighter.all();
</script>

<body>태그를 아래와 같이 번경

1
<body Onload="dp.SyntaxHighlighter.HighlightAll('code');">

 

3. 글쓸 때 적용방법

1
2
3
4
5
6
7
8
9
<textarea name="code" class="brush:cpp;">
#include <iostream>
using namespace std;
  
void main(){
  cout << "PRINT!";
}
  
</TEXTAREA>

 

'Etc > Blogging' 카테고리의 다른 글

TISTORY 초대장 있어요.  (0) 2016.11.28

hackapk.py

모바일 점검을 하다보면 매번 툴을 이용해서 디컴파일 하고 디버깅을 위해서 debuggable옵션을 true로 바꿔주고 다시 리컴파일 하고 사이닝 하고, 하는 일련의 작업들을 반복하게 된다.

따라서 필자는 이 귀찮은 작업을 피하고자, 반복 잡업을 수행해주는 Python 스크립트를 하나 만들었는데 아래에 공개 하도록 한다.

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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
# -*-coding: utf-8 -*- Python 2.7에서 한글 경로 입력을 위해 Python 설치 폴더의 Lib 밑 site.py - setencoding()함수의 첫 if문을 1로 변경
 
import os, subprocess
 
import optparse, zipfile, sys
 
import xml.etree.ElementTree as ET
 
 
 
def am(base_path): # adb shell root 권한으로 실행후 액티비티 강제 호출. 악의적인 행위가 가능하면 취약점
 
    f = open(base_path+'\\activity.bat','w')
 
    global sharedUserId
 
    global debuggable
 
 
 
    tree = ET.parse(base_path+'\\apktool\\AndroidManifest.xml')
 
    root = tree.getroot()
 
 
 
    package = root.attrib['package']
 
    try:# shareduserid가 설정되어있는지 확인
 
        sharedUserId = bool(application.attrib['{http://schemas.android.com/apk/res/android}sharedUserId'])
 
    except Exception as e:
 
        pass
 
    for application in root.findall('application'):
 
        try:# debuggable이 설정되어있는지 확인
 
            debuggable = bool(application.attrib['{http://schemas.android.com/apk/res/android}debuggable'])
 
        except Exception as e:
 
            pass
 
        for activity in application.findall('activity'):
 
            activity_name = activity.attrib['{http://schemas.android.com/apk/res/android}name']
 
            for intent_filter in activity.findall('intent-filter'):
 
                action = intent_filter.find('action')
 
                if action is not None:
 
                    action_name = action.attrib['{http://schemas.android.com/apk/res/android}name']
 
            if action_name != '':
 
                cmd = 'adb shell ' + 'su -c "'+ 'am start'  + ' -a android.intent.action.MAIN '+ ' -n ' + package+'/'+activity_name+' -el--es key value' + '" ' +'\n'
 
            else :
 
                cmd = 'adb shell am start'
 
            f.write(cmd)
 
            f.flush()
 
    f.close()
 
    return ""
 
 
 
def debuggable_true(base_path):
 
    tree = ET.parse(base_path+'\\AndroidManifest.xml')
 
    root = tree.getroot()
 
 
 
    for application in root.findall('application'):
 
        try:# debuggable을 True로 변경
 
            application.set('{http://schemas.android.com/apk/res/android}debuggable','True')
 
        except Exception as e:
 
            pass
 
    output_file = open(base_path+'\\AndroidManifest.xml', 'w' )
 
    output_file.write(ET.tostring(root).replace('ns0','android'))
 
    output_file.close()
 
    return ""
 
 
 
def execute_cmd(cmd): # 명령프롬프트를 통해 명령 실행
 
    my_env=os.environ
 
    my_env["PATH"]=os.path.dirname(__file__)+'\\apk-sign;'+os.path.dirname(__file__)+'\\apktool;'+os.path.dirname(__file__)+'\\jadx\\bin;'+my_env["PATH"]
 
    print cmd,
 
    p = subprocess.Popen(cmd, env=my_env, shell=True, stdout=subprocess.PIPE)
 
    line = p.stdout.readline()
 
    if line !='':
 
        print ''
 
        while True:
 
            if line != '':
 
                #the real code does filtering here
 
                strip = line.rstrip()
 
                print strip
 
                line = p.stdout.readline()
 
            else:
 
                    break
 
    print " ----- Done! "
 
    print ""
 
    return ""
 
 
 
def execute_new_cmd(cmd): # 명령프롬프트를 통해 명령 실행
 
    print cmd,
 
    os.system('start /wait cmd /c "mode con: cols=50 lines=30 & '+cmd+'" ')
 
    print " ----- Done! "
 
    return ""
 
 
 
def unzip(apkfile, output): # 대상 apk 파일 압축해제
 
    with zipfile.ZipFile(apkfile, "r") as z:
 
        z.extractall(output)
 
    return ""
 
 
 
def apktool_unpack(apkfile, output): # 대상 apk 파일 unpacking 및 디버깅을 위한 -d옵션 unpacking
 
    execute_cmd('apktool d "'+apkfile+'" -o "'+output+'" ')
 
    execute_cmd('apktool d -d "'+apkfile+'" -o "'+output+'_d"')
 
    return ""
 
 
 
def apktool_repack(output): # 대상 apk 파일 debuggable true
 
    debuggable_true(output)
 
    execute_cmd('apktool b "'+output+'" ')
 
    autosign(output)
 
    return ""
 
 
 
def autosign(output): # 대상 apk 파일 unpacking 및 디버깅을 위한 -d옵션 unpacking
 
    dist_apkfile = output+'\\dist\\' +output.split('\\').pop(-2)+'.apk'
 
    execute_cmd('sign "'+ dist_apkfile +'" "' + output + "\\..\\" + dist_apkfile.split('\\').pop(-1)[0:-4] +'_signed.apk"')
 
    return ""
 
 
 
def jadx(apkfile, output): # jadx로 decompile
 
    execute_cmd('jadx -f -d "'+output+'" "'+apkfile+'" ')
 
    return ""
 
 
 
def jadx_gui(input): # jadx로 decompile
 
    execute_cmd('jadx-gui "'+ input + '" ')
 
    return ""
 
 
 
def main():
 
    global debuggable
 
 
 
    parser = optparse.OptionParser('1. usage hackapk.py -i apkfile.apk -o output dir\n2. usage hackapk.py filepath\\victim.apk\n3. usage hackapk.py -b build_targer_dir\n4. usage hackapk.py -p pakage_name\n using -b, -p options solo.')
 
    parser.add_option('-i', dest='input'type='string', help='apkfile.apk filepath') # 입력 apk
 
    parser.add_option('-o', dest='output', type='string', help='output dir path'# 출력 폴더 지정
 
    parser.add_option('-b', dest='build_target', type='string', help='build targer dir') # 빌드 후 사이닝 해주는 옵션
 
    parser.add_option('-p', dest='pull_pakage', type='string', help='pull pakage') # pakage 데이터 긁어오는 옵션
 
    (options, args) = parser.parse_args()
 
    input = options.input
 
    output = options.output
 
    build_target = options.build_target
 
    pull_pakage = options.pull_pakage
 
     
 
    if pull_pakage ==None :
 
        if build_target == None :
 
            if (input == None) & (output == None) :
 
                if sys.argv[1][-4:] == '.apk' :
 
                    input=os.path.abspath(sys.argv[1])
 
                else :
 
                    print parser.usage
 
                    exit(0)
 
                base_path = input[0:-4]
 
            elif (input != None) & (output != None) :
 
                input=os.path.abspath(input)
 
                filename = input.split('\\').pop()
 
                output=os.path.abspath(output)
 
                base_path = output+"\\"+filename[0:-4]
 
            else :
 
                print parser.usage
 
                exit(0)
 
 
 
            #execute_cmd('set path='+os.path.dirname(__file__)+'\\apk-sign;'+os.path.dirname(__file__)+'\\apktool;'+os.path.dirname(__file__)+'\\jadx\\bin;')
 
                         
 
            execute_cmd('rm -rf "'+base_path+'" ')
 
            execute_cmd('mkdir "'+base_path+'" ')
 
             
 
            unzip_path= base_path+'\\unzip'
 
            execute_cmd('mkdir "'+unzip_path+'" ')
 
            unzip(input, unzip_path)
 
 
 
            jadx_path = base_path+'\\jadx'
 
            execute_cmd('mkdir "'+jadx_path+'" ')
 
            jadx(input, jadx_path)
 
 
 
            apktool_path = base_path+'\\apktool'
 
            apktool_unpack(input, apktool_path)
 
             
 
            print "--- check debuggable options ..."
 
            am(base_path)
 
 
 
            if sharedUserId:
 
                print "!!!!! sharedUserId option is detected - confirm"
 
            else:
 
                print "--- sharedUserId option is not detected"
 
            if debuggable:
 
                print "!!!!! debuggable option is True - danger !!!!!"
 
            else:
 
                print "--- debuggable options is " + str(debuggable)
 
                print "--- Change debuggable TRUE in apktool DIR and Repacking..."
 
                apktool_repack(apktool_path)   
 
            jadx_gui(input)
 
        elif (build_target != None) & (input == None) & (output == None) :
 
            build_target=os.path.abspath(build_target)
 
            apktool_repack(build_target)
 
        else :
 
            print parser.usage
 
            exit(0)
 
    elif (pull_pakage != None) & (build_target == None) & (input == None) & (output == None) :
 
        execute_cmd('adb shell ' + 'su -c "'+'chmod -R 777 /data/data/"')
 
        execute_cmd('adb shell ' + 'su -c "'+'chmod -R 777 /data/data/'+pull_pakage+'" ')
 
        execute_cmd('adb pull ' + '/data/data/'+pull_pakage+'/'+' ./')
 
    else :
 
            print parser.usage
 
            exit(0)
 
             
 
 
 
if __name__ == '__main__':
 
    sharedUserId = False
 
    debuggable = False
 
 
 
    print "Hack-apk Made by Y.Prefer"
 
    print "Hack-apk is running....."
 
    print ""
 
    main()
 
    print "END"

 

소스를 보면 알겠지만 복잡한 부분은 없고.


사용방법으로 옵션은 총 4가지가 있는데

-i 옵션 : 입력 apk 파일을 지정해 주는 옵션

-o 옵션 : 출력 폴더를 지정해 주는 옵션

-b 옵션 : 이 뒤에 넣는 폴더를 빌드하고 사이닝 해서 apk 파일로 떨궈주는 옵션

-p 옵션 adb shell 을 이용해 package 안에 있는 파일을 긁어오는 옵션

 

으로 한번 해보면 알 수 있을건데, 잘 모르겠다면 친절히 공개해준 소스를 분석해보길 바란다.

 

기본적으로 사용할 때는 옵션을 넣지 않고, 아래와 같이 apk 파일 명을 입력값으로 넣어주면 되는데 그러면 결과는 아래와 같이 떨어진다.


뭐 보면 알겠지만 특별한건 없고 하나씩 실행시켜주는 거고,

debuggable과 sharedUserId가 설정되어있는지 체크해주고, 요렇게 디렉토리들을 아웃풋으로 출력해준다


apktool 폴더는 옵션을 주지 않고 apktool로 디컴파일 한 결과폴더로 jadx로 나온 소스를 분석해 Smali 코드를 변경 할 때 사용할 폴더,

apktool_d는 -d옵션을 주고 apktool로 디컴파일한 결과폴더로 java확장자를 가진 Smali 코드를 Eclipse에 import 하여 동적 디버깅에 사용할 폴더,

jadx는 java source로 디컴파일 해준 폴더로, 가독성이 높아 소스분석을 할때 사용할 폴더,

unzip은 그냥 압축 푼 풀더,

activity.bat은 adb shell을 통해 Apk가 가지고 있는 activity들은 모두 강제 호출 해주는 batch 파일로, 사용자에게 허락되지 않은 activity 호출 여부를 판단할때 사용할 파일,

Test_signed.apk 는 debuggable이 false옵션일때 true로 변경해서 apktool을 이용해 리컴파일 해주고, signing까지 끝내준 apk 파일.


Android APK 진단을 위한 툴 소개

 

네트워크 통신을 하는 앱이라면, 웹 진단 툴을 함께 사용한다.

Apktool

링크 : http://ibotpeaches.github.io/Apktool/

ApkTool은 apk파일은 디컴파일하거나 수정한 후 다시 컴파일 할 수 있는 Tool .

여러 옵션이 있지만 자주 사용하는 옵션은

 d 옵션 : decompile 해주는 옵션으로 smali 파일이 아웃풋

b 옵션 : recompile 해주는 옵션으로 apkfile이 아웃풋으로 나오며, signing을 거쳐 안드로이드폰에 설치가 가능.

d -d 옵션 : decompile 해주는 옵션으로 smali 파일이 아웃풋으로 나오지만, 확장자를 java파일로 만들어주어 동적디버깅 할 때 사용.



apk-sign

링크 : https://github.com/appium/sign

안드로이드에는 signing되지 않은 앱은 설치되지 않음

이 signing은 개발자가 APK파일로 만들어 낼 때 하는데, Apk Tool 을 이용해 decompile을 하면 signing이 풀림.

따라서 폰에 설치를 하기 위해서는 signing을 해주어야 하는데, 원 개발자의 서명을 따라할수는 없으나 아무 keystore를 가지고 signing만 해주어도 설치는 가능.



dex2jar

링크 : https://sourceforge.net/projects/dex2jar/

Apk파일은 안에 classes.dex라는 파일이 있는데 이 파일은 Android Dalvik이 인식할수 있도록 class파일을 바이트 코드로 변환한 파일.

이 파일을 dex2jar를 이용해 class파일을 추출하는 Tool.


jd-gui

링크 : http://jd.benow.ca/

JAVA decompiler 

위 dex2jar를 이용해 추출해낸 class파일을 java로 복원해주는 Tool.

그런데 복원할때 완벽하지 않아 복원이 잘 되지 않는 부분이 있는 것이 아쉬운점.


jadx

링크 : https://github.com/skylot/jadx

JAVA decompiler

필자는 dex2jar&jd-gui 보다 jadx를 사용하는 것을 더 선호하는데 jadx의 결과가 jd-gui보다 좀더 정확하게 복원을 해주는 것으로 느껴지고, 또 dex2jar라는 단계를 밟지 않고 바로 apk파일을 끌어다 놓는 것만으로 디 컴파일이 되기 때문.

 

cheatengine

링크 : http://www.cheatengine.org/

메모리 변조 툴

android 앱에 attach해서 메모리를 변조등을 수행할 수 있다.

 

frida

링크 : http://www.frida.re/docs/android/

frida는 javascript inject를 이용해 개발자가 만들어낸 함수를 공격자가 명시해서 호출하거나, 함수를 새로 만들어서 호출 할 수도 있다.

예를 들면 Getpassword(String id) 이런 함수가 있다면 공격자가 이를 호출하여 password를 얻어낼 수 도 있다.


ida pro

링크 : https://www.hex-rays.com/products/ida/

ida는 동적 디버깅 툴로 대상 Apk를 실행시키면서, 각 부분에 BP를 걸어 그 시점에서의 레지스트리 값등을 확인하고, 패치를 통해

체크로직등의 우회를 노릴수 있다.


drozer

링크 : https://labs.mwrinfosecurity.com/tools/drozer/

안드로이드 진단 프레임워크로 안드로이드 어플리케이션의 보안 취약점을 진단할 수 있다.

 

introspy

링크 : https://github.com/iSECPartners/Introspy-Android

함수 호출을 포함한 어플리케이션 API 안드로이드 API 파라미터와 리턴값을 로깅 해주는 tool이다.

+ Recent posts