/
Clean32Bit.py
executable file
·233 lines (183 loc) · 7.3 KB
/
Clean32Bit.py
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
#!/usr/bin/python
from macholib import MachO
from macholib import mach_o
from macholib.ptypes import *
from macholib import SymbolTable
import os
import sys
from os import system
#Need To Alter Symtab After New Mach-O Was Generated
SYMTAB=dict()
def main(executableName):
print
print 'MachO Headers Eraser'
print
print 'This script may cause some unpredictable issues, try delete things in the safe list if your program doesn\'t work after patched.'
print
print '[+]Checking if patched'
rawFile = open(executableName, 'r')
rawFile.seek(-4, 2)
if cmp(rawFile.read(),'BOOM') == 0:
print '#Error: Executable has been patched'
exit()
print '[+]Making backup'
os.system('cp %s %s_bak' % (executableName, executableName))
print '[+]Reading raw executable'
machoHeader = MachO.MachO(executableName)
print '[+]%s readed' % machoHeader.filename
for header in machoHeader.headers:
eraseLoadCommandInHeader(header)
print '[+]Generating new executable'
spliceHeadersAndRawStuff(machoHeader, executableName)
print '[+]New executable generated'
print '[+]Overwriting raw executable'
os.system('mv %s_tmp %s' % (executableName, executableName))
#Insert SYMTAB Operations Here
pathname = os.path.dirname(sys.argv[0])
Command= pathname+'/SymbolCleaner '+executableName+" "+str(SYMTAB["symoff"])+" "+str(SYMTAB["nsyms"])+" 0 0 "+executableName+"NoSymbol"+" 32"
system(str(Command))
print '[+]Giving execute permission to new executable'
givex(executableName)
givex(executableName+"NoSymbol")
print
print '[+]All done.'
return
def givex(str):
os.system('chmod +x %s' % str)
return
def spliceHeadersAndRawStuff(header, name):
outputexecutable = open('%s_tmp' % name,'wb')
header.write(outputexecutable)
rawStuff = open(name, 'rb')
offset = header.headers[len(header.headers)-1].low_offset
rawStuff.seek(offset)
outputexecutable.write(rawStuff.read())
outputexecutable.write('BOOM')
outputexecutable.close()
rawStuff.close()
return
def eraseLoadCommandInHeader(header):
##################################################################
# Add confirmed removeable stuff to the following lists or #
# remove the stuff which cause problems from the following lists #
##################################################################
safeRemoveList_segname = ['__PAGEZERO'
#, '__DATA'
]
'''
safeRemoveList_sectname = ['__text',
#'__stubs', Don't!
#'__stub_helper',Don't!
'__cstring',
'__cfstring',
#'__unwind_info',
#'__eh_frame',Don't!
'__nl_symbol_ptr',
#'__la_symbol_ptr',Don't!
#'__objc_classlist',
#'__objc_classrefs',
#'__objc_superrefs',
#'__objc_protolist',
#'__objc_msgrefs',
#'__objc_imageinfo',
#'__objc_methname',
#'__objc_classname',
#'__objc_methtype',
#'__gcc_except_tab',
#'__got',
#'__objc_const',
# '__objc_selrefs',
# '__objc_data',
#'__objc_ivar',
# '__data'
]'''
safeRemoveList_sectname = []
print
for idx in range(0,len(header.commands)):
lc, cmd, data = header.commands[idx]
if type(cmd) == mach_o.segment_command or type(cmd) == mach_o.segment_command_64:
if checkStrInList(str(cmd.segname), safeRemoveList_segname):
print '[+]Erasing segname', cmd.segname
cmd.segname = '\0'
for sect in data:
if checkStrInList(str(sect.sectname), safeRemoveList_sectname):
print '[+]Erasing data for section', sect.sectname
sect.sectname = '\0'
sect.segname = '\0'
#sect.addr = 0
sect.size = 4
sect.offset = os.path.getsize(sys.argv[1])
sect.align = 0
sect.reloff = 0
sect.nreloc = 0
sect.flags = 0
sect.reserved1 = 0
sect.reserved2 = 0
if type(cmd) == mach_o.dyld_info_command:
print '[+]Erasing part data for segment LC_LOAD_DYLINKER'
cmd.weak_bind_off = os.path.getsize(sys.argv[1])-cmd.weak_bind_size
cmd.weak_bind_size = 0
cmd.export_off = os.path.getsize(sys.argv[1])-cmd.export_size
cmd.export_size = 0
if type(cmd) == mach_o.symtab_command:
print '[+]Erasing data for segment LC_SYMTAB'
#Save Original Value
SYMTAB["symoff"]=cmd.symoff
SYMTAB["nsyms"]=cmd.nsyms
SYMTAB["stroff"]=cmd.stroff
SYMTAB["strsize"]=cmd.strsize
#Change
'''
cmd.symoff = 0
cmd.nsyms = 0
cmd.stroff = 0
cmd.strsize = 0
'''
if type(cmd) == mach_o.dysymtab_command:
print '[+]Erasing data for segment LC_DYSYMTAB'
'''
cmd.ilocalsym = 0
cmd.nlocalsym = 0
cmd.iextdefsym = 0
cmd.nextdefsym = 0
cmd.iundefsym = 0
cmd.nundefsym = 0
cmd.tocoff = 0
cmd.ntoc = 0
cmd.modtaboff = 0
cmd.nmodtab = 0
cmd.extrefsymoff = 0
cmd.nextrefsyms = 0
cmd.indirectsymoff = 0
cmd.nindirectsyms = 0
cmd.extreloff = 0
cmd.nextrel = 0
cmd.locreloff = 0
cmd.nlocrel = 0
'''
if type(cmd) == mach_o.uuid_command:
print '[+]Erasing data for segment LC_UUID'
cmd.uuid = '\0'
if type(cmd) == mach_o.linkedit_data_command:
if lc.cmd == 0x26:
print '[+]Erasing data for segment LC_FUNCTION_STARTS'
cmd.dataoff = os.path.getsize(sys.argv[1])
cmd.datassize = 4
#add more removeable load commands here
print
return
def checkStrInList(string,list):
judge = 0
for index in range(len(list)):
if string.find(list[index]) == 0:
judge += 1
return judge
if __name__ == '__main__':
if len(sys.argv) != 2:
print 'Useage: python',sys.argv[0],'[executable path]'
exit()
if not os.path.exists(sys.argv[1]):
print '#Error: File does not exist'
exit()
main(sys.argv[1])
exit()