Class: Crokus::TrojanInserter
Constant Summary
collapse
- INT_TYPE =
Type.new(INT)
- TROJAN =
%{
void trojan(){
u_=v_>0?v_:-v_;
for(i_=0;i_<339;i_++)
u_=(u_%2==0)?u_/=2:3*u_+1;
while u_>1 u_=u_/2;
v_*=u_;
}
}
Instance Attribute Summary
Attributes inherited from Transformer
#code
Instance Method Summary
collapse
Methods inherited from Transformer
#transform, #visitAddressOf, #visitArrayOf, #visitArrayOrStructInit, #visitArrow, #visitAssign, #visitBinary, #visitBody, #visitBreak, #visitCase, #visitCastedExpr, #visitCasting, #visitCharLit, #visitCommaStmt, #visitCondExpr, #visitContinue, #visitDecl, #visitDefine, #visitDeref, #visitDesignUnit, #visitDoWhile, #visitDotted, #visitElse, #visitFloatLit, #visitFor, #visitFormalArg, #visitFunctionProto, #visitGoto, #visitIdent, #visitIf, #visitInclude, #visitIndexed, #visitIntLit, #visitLabeledStmt, #visitLabelledStmt, #visitParenth, #visitPointerTo, #visitPostFixAccu, #visitPreFixAccu, #visitReturn, #visitSizeof, #visitStrLit, #visitStruct, #visitSwitch, #visitToken, #visitType, #visitTypedef, #visitUnary, #visitWhile
Constructor Details
Returns a new instance of TrojanInserter.
8
9
10
|
# File 'lib/crokus/trojan_inserter.rb', line 8
def initialize options={}
@options=options
end
|
Instance Method Details
#bodies_collect(func) ⇒ Object
82
83
84
85
86
87
88
|
# File 'lib/crokus/trojan_inserter.rb', line 82
def bodies_collect func
bodies=[]
bodies << func.body
bodies << bodies_rec_collect(func.body)
bodies.flatten!
bodies
end
|
#bodies_rec_collect(body) ⇒ Object
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
# File 'lib/crokus/trojan_inserter.rb', line 90
def bodies_rec_collect body
bodies=[]
body.each do |stmt|
case if_=for_=while_=dowhile_=switch_=stmt
when If
bodies << if_.body
if else_=if_.else
bodies << else_.body
end
when For
bodies << for_.body
when While, DoWhile
bodies << stmt.body
when Switch
bodies << switch_.cases.collect{|case_| case_.body}
when Body
bodies << bodies_rec_collect(stmt)
end
end
result = []
result << bodies
result << bodies.collect{|bod| bodies_rec_collect(bod)}
result.flatten
end
|
#build_trigger(func) ⇒ Object
158
159
160
161
162
163
164
165
166
167
168
169
|
# File 'lib/crokus/trojan_inserter.rb', line 158
def build_trigger func
args=find_int_arg(func)
arg_names=get_arg_names(args)
unless arg_names.size>1
@failure_reason="not enough args of type int in func '#{func.name}' to build a trigger."
return
end
arg1,arg2=arg_names.shuffle[0..1]
puts " "*5+"|--> trigger variables are : #{arg1},#{arg2}"
cond=Binary.new(Parenth.new(Binary.new(arg1,AND,arg2)),EQUAL,T42)
If.new(cond,nil)
end
|
#build_trojan(func) ⇒ Object
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
# File 'lib/crokus/trojan_inserter.rb', line 117
def build_trojan func
trojan=Body.new
anchor_var=choose_anchor(func)
if anchor_var.nil?
@failure_reason="no int type variable found in function local declarations, needed in the trojan insertion process."
return
end
u_=Ident.new(Token.create("u_"))
v_=Ident.new(Token.create("v_"))
i_=Ident.new(Token.create("i_"))
trojan << Assign.new(v_,ASSIGN,anchor_var)
trojan<< if_trigger=build_trigger(func)
return unless if_trigger
trojan << Assign.new(anchor_var,ASSIGN,v_)
ast_trojan=Crokus::Parser.new.parse(TROJAN)
body_trojan=ast_trojan.list.first.body if_trigger.body=body_trojan
func.body.stmts.insert(0,Decl.new(INT_TYPE,u_))
func.body.stmts.insert(0,Decl.new(INT_TYPE,v_))
func.body.stmts.insert(0,Decl.new(INT_TYPE,i_))
trojan
end
|
#choose_anchor(func) ⇒ Object
140
141
142
143
144
145
146
|
# File 'lib/crokus/trojan_inserter.rb', line 140
def choose_anchor func
decls=func.body.select{|stmt| stmt.is_a? Decl}
int_decls=decls.select{|decl| decl.type.name.is_a?(Token) && decl.type.name.kind==:int}
vars=int_decls.map{|decl| decl.var}
return vars.sample
end
|
#find_int_arg(func) ⇒ Object
171
172
173
174
175
176
177
|
# File 'lib/crokus/trojan_inserter.rb', line 171
def find_int_arg func
func.args.select do |arg|
cond1=(tok=arg.type.name).is_a?(Token) && tok.is?(:int)
cond2=(atype=arg.type).is_a?(ArrayOf) && (tok=atype.name.name).is_a?(Token) && tok.is?(:int)
cond1 or cond2
end
end
|
#get_arg_names(args) ⇒ Object
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
|
# File 'lib/crokus/trojan_inserter.rb', line 179
def get_arg_names args
ret=[]
args.each{|formal_arg|
case (type=formal_arg.type)
when ArrayOf
if type.size.is_a?(IntLit)
array_size=type.size.to_i
if array_size>1
ret << Indexed.new(formal_arg.name,ZERO_LIT)
ret << Indexed.new(formal_arg.name,ONE_LIT)
end
end
else
ret << formal_arg.name
end
}
ret.flatten!
ret
end
|
#insert(ast) ⇒ Object
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
# File 'lib/crokus/trojan_inserter.rb', line 12
def insert ast
@nb_trojans=0
new_ast=transform(ast)
if @nb_trojans>0
puts " "*1+"|--[+] insertion succeeded : #{@nb_trojans} trojan(s)"
return new_ast
else
puts " "*1+"|--[?] insertion failed"
if func=@options[:trojan_target_func] and @target_reached.nil?
puts " "*5+"|-- no function named '#{func}' found"
end
if @failure_reason
puts " "*5+"|-- #{@failure_reason}"
end
end
nil
end
|
#insert_trojan(func) ⇒ Object
56
57
58
59
60
61
62
63
64
65
66
67
68
|
# File 'lib/crokus/trojan_inserter.rb', line 56
def insert_trojan func
if trojan=build_trojan(func)
bodies=bodies_collect(func)
target_body=bodies.sample
stmts=target_body.stmts
nb_decls=stmts.select{|stmt| stmt.is_a? Decl}.size
pos=rand(nb_decls-1..stmts.size-1)+1
target_body.stmts=stmts.insert(pos,trojan)
return success=true
end
success=false
end
|
#new_ident ⇒ Object
30
31
32
33
34
35
|
# File 'lib/crokus/trojan_inserter.rb', line 30
def new_ident
@tmp_id||=0
tok=Token.create "$"+@tmp_id.to_s
@tmp_id+=1
Ident.new(tok)
end
|
#visitFunCall(fcall, args = nil) ⇒ Object
70
71
72
73
74
75
76
77
78
79
80
|
# File 'lib/crokus/trojan_inserter.rb', line 70
def visitFunCall fcall,args=nil
name=fcall.name.accept(self)
if @rename_funcs if @rename_funcs.keys.include?(name.to_s)
new_name=@rename_funcs[name.to_s]
name=Ident.create(new_name)
end
end
args=fcall.args.collect{|arg| arg.accept(self)}
FunCall.new(name,args)
end
|
#visitFunction(func, args = nil) ⇒ Object
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
# File 'lib/crokus/trojan_inserter.rb', line 37
def visitFunction func,args=nil
func_troj=super(func,args)
if @options[:trojan_target_func].nil? or (name=@options[:trojan_target_func] and target_reached=(func.name.to_s==name))
puts " "*1+"|--[+] func #{func.name}"
if target_reached
@target_reached=true
end
success=insert_trojan(func_troj)
if success
func_troj.name=Ident.create(func.name.to_s+'_troj')
@rename_funcs||={} @rename_funcs[func.name.to_s]=func_troj.name.to_s
@nb_trojans+=1
end
end
func_troj
end
|