'Develop/UTIL' 카테고리의 글 목록 :: YPrefer's Develop&Security

이전에 올린 java와 기능은 같다.

내가 한 것은 아니가 동료가 java용은 설치해야 한다고 귀찮다며 만들어서 주었다.


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
#-*- coding: utf-8 -*-
import _winreg as winreg
import binascii
import ctypes
import time
 
 
 
#################유저가 설정할 부분####################
 
proxy_server_addr = '127.0.0.1:8080' #프록시서버 주소
auto_config_url ='' #pac파일 넣는부분
auto_config_mode = 1     # 자동구성 2개 항목중 어떤것을 껐다 켤지 선택
#1:자동으로 설정검색만 on/off
#2:자동구성 스크립트 사용 부분만 on/off
#3:둘다 on/off
 
####################################################
 
 
 
 
 
#INTERNET_SETTINGS 이하경로  proxy 사용여부 on/off
INTERNET_SETTINGS = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
    r'Software\Microsoft\Windows\CurrentVersion\Internet Settings',
    0, winreg.KEY_ALL_ACCESS)
 
#Connections 이하 경로 , 자동구성 사용여부 
Connections = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
    r'Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections',
    0, winreg.KEY_ALL_ACCESS)
 
 
#레지스트리에 값 입력
def set_key(key, subkey, value):
    _, reg_type = winreg.QueryValueEx(key, subkey)
    winreg.SetValueEx(key, subkey, 0, reg_type, value)
 
 
###############자동으로 설정검색 체크 부분 START########################
(value , regtype) = winreg.QueryValueEx(Connections, "DefaultConnectionSettings")
 
 
def auto_config_Enable():
    auto_config = binascii.b2a_hex(value)
    #auto_config = auto_config[:8] + '02' + auto_config[10:]
    auto_config = auto_config[:16] +'09' + auto_config[18:]
    auto_config = binascii.a2b_hex(auto_config)
    set_key(Connections, 'DefaultConnectionSettings' , auto_config)
                                                        
def auto_config_Disable():
    auto_config = binascii.b2a_hex(value)
    #auto_config = auto_config[:8] + '01' + auto_config[10:]
    auto_config = auto_config[:16] +'01' + auto_config[18:]
    auto_config = binascii.a2b_hex(auto_config)
    set_key(Connections, 'DefaultConnectionSettings' , auto_config)
 
####################################################################
 
     
 
#proxy on/off 여부를 나타내는 flag
proxy_status = winreg.QueryValueEx(INTERNET_SETTINGS,'ProxyEnable')
 
proxy_flag=proxy_status[0]
 
# proxy on
def Proxy_Enable():
      
    set_key(INTERNET_SETTINGS,'ProxyEnable', 1)
    set_key(INTERNET_SETTINGS,'ProxyServer', proxy_server_addr)
 
# proxy off   
def Proxy_Disable():
         
    set_key(INTERNET_SETTINGS,'ProxyEnable', 0)
     
 
#브라우저 설정 새로고침
def refresh():
    INTERNET_OPTION_REFRESH = 37
    INTERNET_OPTION_SETTINGS_CHANGED = 39
 
    internet_set_option = ctypes.windll.Wininet.InternetSetOptionW
 
    internet_set_option(0, INTERNET_OPTION_REFRESH, 0, 0)
    internet_set_option(0, INTERNET_OPTION_SETTINGS_CHANGED, 0, 0)
 
 
#자동구성 on
winreg.SetValueEx(INTERNET_SETTINGS,'AutoConfigURL',0,1,auto_config_url)
 
#자동구성스크립트 off
#winreg.SetValueEx(INTERNET_SETTINGS,'AutoConfigURL',0,0,"")
 
 
if proxy_flag==0:
    Proxy_Enable()
    auto_config_Disable()
    winreg.SetValueEx(INTERNET_SETTINGS,'AutoConfigURL',0,1,'')
    print "Proxy_Enable"
 
if proxy_flag==1:
    Proxy_Disable()
    #auto_config_Enable()   
    winreg.SetValueEx(INTERNET_SETTINGS,'AutoConfigURL',0,1,auto_config_url)
    print "Proxy_Disable"
     
refresh()
 
#time.sleep(0.15)


Fortify 라는 소스점검도구가 있다.

이 점검도구를 이용하면 소스코드를 빌딩하면서 어떤 소스파일의 어디라인데서 취약점이 있다고 보여진다 라는 레포팅을 만들어 준다.

이러한 결과는 개발자에게 전달되는데, 최신버전의 Fortify 는 그렇지 않지만

구버전의 Fortify는 레포트의 형태가 XML, PDF, WORD 파일 이 3가지로 떨어진다.


근데 문제는, 취약점이 적게는 몇천개 많게는 수십만개까지 잡히는데 이것을 word나 xml로 보면 굉장히 불편하다는 점이다.

(그래서 최신버전에는 excel로 레포팅을 하게 만들었겟지만.. 그럼에도 보기는 불편하긴 하다.)

그래서 그 결과는 나름대로 보기편하게 필요한 요소만 뽑아내서 파싱해주도록했다.


점검자는 개발자 입장에서 보면 딴지걸고 시비거는 사람으로 밖에 안보이겠지만...,

그래도 조금이라도 편하게 조치하시기를 바라는 마음에서 만들어보았다.


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
# -*-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
import xlsxwriter
 
def main():
     
    row = 0
    file_count =0
    base_xml_report = sys.argv[1]
    output_xls_report = sys.argv[1][0:-4] + '.xlsx'
    workbook = xlsxwriter.Workbook(output_xls_report)
    worksheet = workbook.add_worksheet()
 
    tree = ET.parse(base_xml_report)
    root = tree.getroot()
    row = 0
    title_forrmat = workbook.add_format({'border':1})
    title_forrmat.set_bold()
    title_forrmat.set_bg_color('yellow')
    worksheet.write(row,0,"Index",title_forrmat)
    worksheet.write(row,1,"Category",title_forrmat)
    worksheet.write(row,2,"Friority",title_forrmat)
    worksheet.write(row,3,"Value",title_forrmat)
    worksheet.write(row,4,"FileName",title_forrmat)
    worksheet.write(row,5,"FilePath",title_forrmat)
    worksheet.write(row,6,"LineStart",title_forrmat)
 
    content_format = workbook.add_format({'border':1})
 
    for issue in root.iter('Issue'):
        row = row+1
        worksheet.write(row,0,row,content_format)
        worksheet.write(row,1,issue.findtext("Category"),content_format)
        worksheet.write(row,2,issue.findtext("Friority"),content_format)
        for tag in issue.findall('Tag'):
            worksheet.write(row,3,tag.findtext("Value"),content_format)
        for primary in issue.findall('Primary'):
            worksheet.write(row,4,primary.findtext("FileName"),content_format)
            worksheet.write(row,5,primary.findtext("FilePath"),content_format)
            worksheet.write(row,6,primary.findtext("LineStart"),content_format)
 
    workbook.close()
    return ""
     
if __name__ == '__main__':
    print "Parser Fortify XML Made by Y.Prefer"
    print "Parser Fortify XML is running....."
    print ""
    if len(sys.argv) == 2 and sys.argv[1][-4:] == ".xml":
        main()
    else:
        print "Please Input XML File"
 
    print "END"


필자의 회사의 경우 보안을 위해 외부 인터넷 망과 연결시 Proxy를 통해야 한다.

그런데, 보안점검을 하다보면 Proxy를 Burpsuite나 Fiddler와 같은 Tool의 포트로 변경해줘야 하는 일이 있는데,

이걸 매번 브라우저의 설정탭을 찾아 들어가 변경하기도 귀찮고,

그렇다고 Cooxie Toolbar같은걸 번거롭게 설치해서 마우스 클릭질 하는 것도 맘에 들지 않아서, Java로 변경해주는 걸 하나 만들어 보았다.


이 방법은 Java를 이용해 Registery 값을 수정하는 방법인데, Chrome과 IE는 적용되지만 FireFox는 따로 Proxy 정보를 저장하고 있어 적용되지 않는다.


소스를 보면, 간단하다.

Proxy.java

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
package oneclickproxy;
 
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
 
import javax.swing.JDialog;
import javax.swing.JOptionPane;
 
import ca.beq.util.win32.registry.RegistryKey;
import ca.beq.util.win32.registry.RegistryValue;
import ca.beq.util.win32.registry.RootKey;
import ca.beq.util.win32.registry.ValueType;
import oneclickproxy.WinInet.INTERNET_PER_CONN_OPTION_LIST;
public class proxy {
 
    private static final String REGEDIT_KEY = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings";
    private static final String PROXY_VALUE = "ProxyEnable";
    private static final String AUTOCONFIG_VALUE = "AutoConfigURL";
    private static final String PROXYOVERRIDE_VALUE = "ProxyOverride";
    private static final String PROXYSERVER_VALUE = "ProxyServer";
    private static final String REGISTRY_LIBRARY_PATH = "\\lib\\jRegistryKey.dll";
    private static final String CONFIG_FILEPATH = "\\dat\\config.dat";
     
    static INTERNET_PER_CONN_OPTION_LIST list = new INTERNET_PER_CONN_OPTION_LIST();
     
    public static void main(String[] args) {
        // Load JNI library
//      System.out.println(System.getProperty("java.library.path"));
//      System.out.println(new File(".").getAbsolutePath()+REGISTRY_LIBRARY_PATH);
        RegistryKey.initialize(new File(".").getAbsolutePath()
                + REGISTRY_LIBRARY_PATH);
 
        proxy proxy = new proxy();
        int before = proxy.getProxyEnable(); // 0 :: enable 1 :: able
        int after = before;
        System.out.println("before :: " + before);
        do {
            proxy.setconfigurl(before);
            after = proxy.setProxyEnable(before);
            System.out.println("mid :: " + after);
        } while (before == after);
        System.out.println("after :: " + after);
 
        JOptionPane op = new JOptionPane(after == 0 ? "���Ͻü�����\n��Ȱ��ȭ�Ǿ����ϴ�."
                : "���Ͻü�����\nȰ��ȭ�Ǿ����ϴ�.", after == 0 ? JOptionPane.ERROR_MESSAGE
                : JOptionPane.INFORMATION_MESSAGE);
        WinInet.INSTANCE.InternetSetOption(null,
                WinInet.INTERNET_OPTION_PER_CONNECTION_OPTION, null, 0);
        WinInet.INSTANCE.InternetSetOption(null,
                WinInet.INTERNET_OPTION_SETTINGS_CHANGED, null, 0);
        WinInet.INSTANCE.InternetSetOption(null,
                WinInet.INTERNET_OPTION_REFRESH, null, 0);
        RegistryKey.initialize(new File(".").getAbsolutePath()
                + REGISTRY_LIBRARY_PATH);
        final JDialog dialog = op.createDialog("OCP 1.4 made by Y.S.H");
        dialog.setAlwaysOnTop(true); // <-- this line
 
        ScheduledExecutorService sch = Executors.newSingleThreadScheduledExecutor();    
        sch.schedule(new Runnable() {
            public void run() {
                dialog.setVisible(false);
                dialog.dispose();
            }
        }, Integer.parseInt(proxy.get_specificline(3,
                new File(".").getAbsolutePath() + CONFIG_FILEPATH)), TimeUnit.MILLISECONDS);
         
        dialog.setVisible(true);
        dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        dialog.addWindowListener(new WindowAdapter() {
            @Override public void windowClosed(WindowEvent e) {
              System.exit(0);
            }
          });
        System.exit(0);
    }
 
    private void setconfigurl(int a) {
        // TODO Auto-generated method stub
        RegistryKey key = new RegistryKey(RootKey.HKEY_CURRENT_USER,
                REGEDIT_KEY);
        if (a == 0) {
            if (key.hasValue(AUTOCONFIG_VALUE))
                key.deleteValue(AUTOCONFIG_VALUE);
        } else {
            System.out.println(get_specificline(0,
                    new File(".").getAbsolutePath() + CONFIG_FILEPATH));
            RegistryValue value = new RegistryValue(AUTOCONFIG_VALUE,
                    ValueType.REG_SZ, get_specificline(0,
                            new File(".").getAbsolutePath() + CONFIG_FILEPATH));
            key.setValue(value);
        }
        RegistryValue server_value = new RegistryValue();
        server_value.setName(PROXYSERVER_VALUE);
        server_value.setType(ValueType.REG_SZ);
        server_value.setData(get_specificline(1,
                new File(".").getAbsolutePath() + CONFIG_FILEPATH));
        if (key.hasValue(PROXYSERVER_VALUE)) {
            key.setValue(server_value);
        }
        RegistryValue override_value = new RegistryValue();
        override_value.setName(PROXYOVERRIDE_VALUE);
        override_value.setType(ValueType.REG_SZ);
        override_value.setData(get_specificline(2,
                new File(".").getAbsolutePath() + CONFIG_FILEPATH));
 
        if (key.hasValue(PROXYOVERRIDE_VALUE)) {
            key.setValue(override_value);
        }
    }
 
    private int getProxyEnable() {
        RegistryKey key = new RegistryKey(RootKey.HKEY_CURRENT_USER,
                REGEDIT_KEY);
        RegistryValue value = key.getValue(PROXY_VALUE);
 
        if (key.hasValue(PROXY_VALUE)) {
            return Integer.parseInt(value.getData().toString());
        }
        return 0;
    }
 
    private int setProxyEnable(int enable) {
        RegistryKey key = new RegistryKey(RootKey.HKEY_CURRENT_USER,
                REGEDIT_KEY);
        RegistryValue value = new RegistryValue();
        value.setName(PROXY_VALUE);
        value.setType(ValueType.REG_DWORD_BIG_ENDIAN);
        int after = enable == 0 ? 1 : 0;
        value.setData(after);
 
        if (key.hasValue(PROXY_VALUE)) {
            key.setValue(value);
        }
        return after;
    }
 
    public String get_specificline(int lineNumber, String filename) {
        try {
            FileInputStream fs = new FileInputStream(filename);
            BufferedReader br = new BufferedReader(new InputStreamReader(fs));
            for (int i = 0; i < lineNumber; ++i) {
                br.readLine();
            }
            return br.readLine();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return "FAIL";
    }
}


WinInet.java

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
package oneclickproxy;
 
import java.util.Arrays;
import java.util.List;
 
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.Union;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;
 
public interface WinInet extends StdCallLibrary {
    WinInet INSTANCE = (WinInet) Native.loadLibrary("wininet", WinInet.class,
            W32APIOptions.UNICODE_OPTIONS);
 
    public static final int INTERNET_PER_CONN_FLAGS = 1;
    public static final int INTERNET_PER_CONN_PROXY_SERVER = 2;
    public static final int INTERNET_PER_CONN_PROXY_BYPASS = 3;
    public static final int INTERNET_PER_CONN_AUTOCONFIG_URL = 4;
    public static final int INTERNET_PER_CONN_AUTODISCOVERY_FLAGS = 5;
    public static final int INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL = 6;
    public static final int INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS = 7;
    public static final int INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME = 8;
    public static final int INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL = 9;
 
    public static final int PROXY_TYPE_DIRECT = 0x00000001; // direct to net
    public static final int PROXY_TYPE_PROXY = 0x00000002; // via named proxy
    public static final int PROXY_TYPE_AUTO_PROXY_URL = 0x00000004; // autoproxy
                                                                    // URL
    public static final int PROXY_TYPE_AUTO_DETECT = 0x00000008; // use
                                                                    // autoproxy
                                                                    // detection
 
    //
    // options manifests for Internet{Query|Set}Option
    //
 
    public static final int INTERNET_OPTION_CALLBACK = 1;
    public static final int INTERNET_OPTION_CONNECT_TIMEOUT = 2;
    public static final int INTERNET_OPTION_CONNECT_RETRIES = 3;
    public static final int INTERNET_OPTION_CONNECT_BACKOFF = 4;
    public static final int INTERNET_OPTION_SEND_TIMEOUT = 5;
    public static final int INTERNET_OPTION_CONTROL_SEND_TIMEOUT = INTERNET_OPTION_SEND_TIMEOUT;
    public static final int INTERNET_OPTION_RECEIVE_TIMEOUT = 6;
    public static final int INTERNET_OPTION_CONTROL_RECEIVE_TIMEOUT = INTERNET_OPTION_RECEIVE_TIMEOUT;
    public static final int INTERNET_OPTION_DATA_SEND_TIMEOUT = 7;
    public static final int INTERNET_OPTION_DATA_RECEIVE_TIMEOUT = 8;
    public static final int INTERNET_OPTION_HANDLE_TYPE = 9;
    public static final int INTERNET_OPTION_LISTEN_TIMEOUT = 11;
    public static final int INTERNET_OPTION_READ_BUFFER_SIZE = 12;
    public static final int INTERNET_OPTION_WRITE_BUFFER_SIZE = 13;
 
    public static final int INTERNET_OPTION_ASYNC_ID = 15;
    public static final int INTERNET_OPTION_ASYNC_PRIORITY = 16;
 
    public static final int INTERNET_OPTION_PARENT_HANDLE = 21;
    public static final int INTERNET_OPTION_KEEP_CONNECTION = 22;
    public static final int INTERNET_OPTION_REQUEST_FLAGS = 23;
    public static final int INTERNET_OPTION_EXTENDED_ERROR = 24;
 
    public static final int INTERNET_OPTION_OFFLINE_MODE = 26;
    public static final int INTERNET_OPTION_CACHE_STREAM_HANDLE = 27;
    public static final int INTERNET_OPTION_USERNAME = 28;
    public static final int INTERNET_OPTION_PASSWORD = 29;
    public static final int INTERNET_OPTION_ASYNC = 30;
    public static final int INTERNET_OPTION_SECURITY_FLAGS = 31;
    public static final int INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT = 32;
    public static final int INTERNET_OPTION_DATAFILE_NAME = 33;
    public static final int INTERNET_OPTION_URL = 34;
    public static final int INTERNET_OPTION_SECURITY_CERTIFICATE = 35;
    public static final int INTERNET_OPTION_SECURITY_KEY_BITNESS = 36;
    public static final int INTERNET_OPTION_REFRESH = 37;
    public static final int INTERNET_OPTION_PROXY = 38;
    public static final int INTERNET_OPTION_SETTINGS_CHANGED = 39;
    public static final int INTERNET_OPTION_VERSION = 40;
    public static final int INTERNET_OPTION_USER_AGENT = 41;
    public static final int INTERNET_OPTION_END_BROWSER_SESSION = 42;
    public static final int INTERNET_OPTION_PROXY_USERNAME = 43;
    public static final int INTERNET_OPTION_PROXY_PASSWORD = 44;
    public static final int INTERNET_OPTION_CONTEXT_VALUE = 45;
    public static final int INTERNET_OPTION_CONNECT_LIMIT = 46;
    public static final int INTERNET_OPTION_SECURITY_SELECT_CLIENT_CERT = 47;
    public static final int INTERNET_OPTION_POLICY = 48;
    public static final int INTERNET_OPTION_DISCONNECTED_TIMEOUT = 49;
    public static final int INTERNET_OPTION_CONNECTED_STATE = 50;
    public static final int INTERNET_OPTION_IDLE_STATE = 51;
    public static final int INTERNET_OPTION_OFFLINE_SEMANTICS = 52;
    public static final int INTERNET_OPTION_SECONDARY_CACHE_KEY = 53;
    public static final int INTERNET_OPTION_CALLBACK_FILTER = 54;
    public static final int INTERNET_OPTION_CONNECT_TIME = 55;
    public static final int INTERNET_OPTION_SEND_THROUGHPUT = 56;
    public static final int INTERNET_OPTION_RECEIVE_THROUGHPUT = 57;
    public static final int INTERNET_OPTION_REQUEST_PRIORITY = 58;
    public static final int INTERNET_OPTION_HTTP_VERSION = 59;
    public static final int INTERNET_OPTION_RESET_URLCACHE_SESSION = 60;
    public static final int INTERNET_OPTION_ERROR_MASK = 62;
    public static final int INTERNET_OPTION_FROM_CACHE_TIMEOUT = 63;
    public static final int INTERNET_OPTION_BYPASS_EDITED_ENTRY = 64;
    public static final int INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO = 67;
    public static final int INTERNET_OPTION_CODEPAGE = 68;
    public static final int INTERNET_OPTION_CACHE_TIMESTAMPS = 69;
    public static final int INTERNET_OPTION_DISABLE_AUTODIAL = 70;
    public static final int INTERNET_OPTION_MAX_CONNS_PER_SERVER = 73;
    public static final int INTERNET_OPTION_MAX_CONNS_PER_1_0_SERVER = 74;
    public static final int INTERNET_OPTION_PER_CONNECTION_OPTION = 75;
    public static final int INTERNET_OPTION_DIGEST_AUTH_UNLOAD = 76;
    public static final int INTERNET_OPTION_IGNORE_OFFLINE = 77;
    public static final int INTERNET_OPTION_IDENTITY = 78;
    public static final int INTERNET_OPTION_REMOVE_IDENTITY = 79;
    public static final int INTERNET_OPTION_ALTER_IDENTITY = 80;
    public static final int INTERNET_OPTION_SUPPRESS_BEHAVIOR = 81;
    public static final int INTERNET_OPTION_AUTODIAL_MODE = 82;
    public static final int INTERNET_OPTION_AUTODIAL_CONNECTION = 83;
    public static final int INTERNET_OPTION_CLIENT_CERT_CONTEXT = 84;
    public static final int INTERNET_OPTION_AUTH_FLAGS = 85;
    public static final int INTERNET_OPTION_COOKIES_3RD_PARTY = 86;
    public static final int INTERNET_OPTION_DISABLE_PASSPORT_AUTH = 87;
    public static final int INTERNET_OPTION_SEND_UTF8_SERVERNAME_TO_PROXY = 88;
    public static final int INTERNET_OPTION_EXEMPT_CONNECTION_LIMIT = 89;
    public static final int INTERNET_OPTION_ENABLE_PASSPORT_AUTH = 90;
 
    public static final int INTERNET_OPTION_HIBERNATE_INACTIVE_WORKER_THREADS = 91;
    public static final int INTERNET_OPTION_ACTIVATE_WORKER_THREADS = 92;
    public static final int INTERNET_OPTION_RESTORE_WORKER_THREAD_DEFAULTS = 93;
    public static final int INTERNET_OPTION_SOCKET_SEND_BUFFER_LENGTH = 94;
    public static final int INTERNET_OPTION_PROXY_SETTINGS_CHANGED = 95;
 
    public static final int INTERNET_OPTION_DATAFILE_EXT = 96;
 
    // BOOL InternetSetOption(
    // _In_ HINTERNET hInternet,
    // _In_ DWORD dwOption,
    // _In_ LPVOID lpBuffer,
    // _In_ DWORD dwBufferLength
    // );
    public boolean InternetSetOption(Pointer hInternet, int dwOption,
            Pointer lpBuffer, int dwBufferLength);
 
    // typedef struct _FILETIME {
    // DWORD dwLowDateTime;
    // DWORD dwHighDateTime;
    // } FILETIME, *PFILETIME;
    public static class FILETIME extends Structure {
        public static class ByReference extends FILETIME implements
                Structure.ByReference {
            public ByReference() {
            }
 
            public ByReference(Pointer memory) {
                super(memory);
            }
        }
 
        public FILETIME() {
        }
 
        public FILETIME(Pointer memory) {
            super(memory);
            read();
        }
 
        public int dwLowDateTime;
        public int dwHighDateTime;
 
        @SuppressWarnings("rawtypes")
        @Override
        protected List getFieldOrder() {
            return Arrays.asList(new String[] { "dwLowDateTime",
                    "dwHighDateTime" });
        }
    }
 
    // typedef struct {
    // DWORD dwOption;
    // union {
    // DWORD dwValue;
    // LPTSTR pszValue;
    // FILETIME ftValue;
    // } Value;
    // } INTERNET_PER_CONN_OPTION, *LPINTERNET_PER_CONN_OPTION;
    public static class INTERNET_PER_CONN_OPTION extends Structure {
        public static class ByReference extends INTERNET_PER_CONN_OPTION
                implements Structure.ByReference {
            public ByReference() {
            }
 
            public ByReference(Pointer memory) {
                super(memory);
            }
        }
 
        public INTERNET_PER_CONN_OPTION() {
        }
 
        public INTERNET_PER_CONN_OPTION(Pointer memory) {
            super(memory);
            read();
        }
 
        public static class VALUE_UNION extends Union {
            public int dwValue;
            public String pszValue;
            public FILETIME ftValue;
        }
 
        public int dwOption;
        public VALUE_UNION Value = new VALUE_UNION();
 
        @SuppressWarnings("rawtypes")
        @Override
        protected List getFieldOrder() {
            return Arrays.asList(new String[] { "dwOption", "Value" });
        }
    }
 
    // typedef struct {
    // DWORD dwSize;
    // LPTSTR pszConnection;
    // DWORD dwOptionCount;
    // DWORD dwOptionError;
    // LPINTERNET_PER_CONN_OPTION pOptions;
    // } INTERNET_PER_CONN_OPTION_LIST, *LPINTERNET_PER_CONN_OPTION_LIST;
    public static class INTERNET_PER_CONN_OPTION_LIST extends Structure {
        public static class ByReference extends INTERNET_PER_CONN_OPTION_LIST
                implements Structure.ByReference {
            public ByReference() {
            }
 
            public ByReference(Pointer memory) {
                super(memory);
            }
        }
 
        public INTERNET_PER_CONN_OPTION_LIST() {
        }
 
        public INTERNET_PER_CONN_OPTION_LIST(Pointer memory) {
            super(memory);
            read();
        }
 
        public int dwSize;
        public String pszConnection;
        public int dwOptionCount;
        public int dwOptionError;
        public INTERNET_PER_CONN_OPTION.ByReference pOptions;
 
        @SuppressWarnings("rawtypes")
        @Override
        protected List getFieldOrder() {
            return Arrays.asList(new String[] { "dwSize", "pszConnection",
                    "dwOptionCount", "dwOptionError", "pOptions" });
        }
    }
}



이 소스는 java에서 registery값에 접근하는 jRegistryKey라는 라이브러리를 사용한다.

그 라이브러리를 이용하기위한 Interface가 WinInet.java이고, 실제 동작하는건 Proxy.java라고 보면 된다.

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

라이브러리 사용하는 방법은 일반적이니 따로 적지 않겠다.


설명하자면, Windows의 Proxy 설정값은 Registery의 CURRENT_USER의 Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings

밑에 위치하게 되고 여기에서 프록시 설정에 대한 값들이 있는데,

ProxyEnable : 현재 프록시가 켜져있는지 아닌지의 값.  0 또는 1

ProxyServer : 프록시 서버 주소

ProxyOverride : 프록시 주소를 사용하지 않는 예외 주소들

AutoConfigURL : 프록시 자동구성 스크립트 주소

이다.


이 값을 이용해 현재 프록시가 켜져 있다면 꺼주고, 꺼져 있다면 같은 폴더의 dat폴더 밑 config.dat파일을 참조하여 값을 읽어와 그 설정과 같이

Proxy 설정을 해준다.

config.dat파일의 첫번째 라인을 자동구성 스크립트에, 두번째라인은 프록시 주소에, 세번째 라인은 예외 주소, 네번째 라인은 다이어로그가 실행되는 시간(1000이 1초) 로 구성된다.


이렇게 만들어진 프로그램을 바로가기로 만들어 우측버튼의 속성을 통해 바로가기키를 지정해두면 단축키로 프록시 활성/비활성화가 가능해진다.


만들어진 Tool로 손쉽게 프록시 활성/비활성화를 하면서 홈페이지을 조지면 된다!

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 파일.

+ Recent posts