Skip to content

Commit b98e4b2

Browse files
author
christophe.duvernois
committed
string encryptiion clean up, skip const char** constant string, they are not encrypted
1 parent 8f72e04 commit b98e4b2

File tree

1 file changed

+41
-107
lines changed

1 file changed

+41
-107
lines changed

lib/Transforms/Obfuscation/AbstractStringEncryptionPass.cpp

Lines changed: 41 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,11 @@ bool AbstractStringEncryptionPass::runOnModule(Module &M) {
3939
if(c){
4040
ConstantDataSequential *cds = dyn_cast<ConstantDataSequential>(c);
4141
if(cds){
42-
if(cds->isString()){
42+
if(cds->isString() || cds->isCString()){
4343
StringGlobalVars.push_back(I);
4444
}else{
45-
if(cds->isCString()){
46-
StringGlobalVars.push_back(I);
47-
}else{
48-
//not a string skip it
49-
//errs() << "WARNING : Can't get string value from " << GV->getName() << " SKIP ENCRYPTION!\n";
50-
}
45+
//not a string skip it
46+
//errs() << "WARNING : Can't get string value from " << GV->getName() << " SKIP ENCRYPTION!\n";
5147
}
5248
}
5349
}
@@ -101,6 +97,38 @@ std::string AbstractStringEncryptionPass::getGlobalStringValue(GlobalVariable* G
10197
}
10298

10399
void AbstractStringEncryptionPass::checkStringsCanBeEncrypted(Module &M, std::vector<GlobalVariable*>& StringGlobalVars) {
100+
// @todo do not encrypt const char** not supported too many case too handle for now ...
101+
// just detect const char**
102+
for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) {
103+
GlobalVariable* GV = I;
104+
if(!GV->hasInitializer())
105+
continue;
106+
107+
ConstantArray* array = dyn_cast<ConstantArray>(GV->getInitializer());
108+
if(array){
109+
for(unsigned int i = 0; i < array->getNumOperands(); i++){
110+
ConstantExpr* ce = dyn_cast<ConstantExpr>(array->getOperand(i));
111+
if(ce == 0)
112+
continue;
113+
114+
GetElementPtrInst *gepElementFromArray = dyn_cast<GetElementPtrInst>(ce->getAsInstruction());
115+
if(gepElementFromArray == 0)
116+
continue;
117+
118+
if(GlobalVariable* gv = dyn_cast<GlobalVariable>(gepElementFromArray->getPointerOperand())){
119+
if(dyn_cast<ConstantDataSequential>(gv->getInitializer())){
120+
std::vector<GlobalVariable*>::iterator it = std::find(StringGlobalVars.begin(), StringGlobalVars.end(), gv);
121+
if(it != StringGlobalVars.end()){
122+
errs() << "WARNING : " << getGlobalStringValue(gv) << " won't be ecnrypted (char** encryption is not supported!)!\n";
123+
StringGlobalVars.erase(it);
124+
}
125+
}
126+
}
127+
}
128+
continue;
129+
}
130+
}
131+
104132
//do not encrypt string that are directly in return instruction
105133
// example : const char* fun(){ return "clear-text"; }
106134
// this can't be encrypted since we have to do some allocation to decrypt the string ...
@@ -116,7 +144,7 @@ void AbstractStringEncryptionPass::checkStringsCanBeEncrypted(Module &M, std::ve
116144
Value* retval = ret->getReturnValue();
117145
if(retval == 0)
118146
continue;
119-
147+
120148
//check if the return value is a load instruction
121149
LoadInst* loadInst = dyn_cast<LoadInst>(retval);
122150
if(loadInst){
@@ -136,9 +164,9 @@ void AbstractStringEncryptionPass::checkStringsCanBeEncrypted(Module &M, std::ve
136164
// handle load i8* getelementptr inbounds ([X x i8]* @string, i32 0, i64 x), align 1
137165
ConstantDataSequential *cds = dyn_cast<ConstantDataSequential>(GV->getInitializer());
138166
if(cds){
139-
errs() << "WARNING : " << getGlobalStringValue(GV) << " cant't be ecnrypted (const char* directly used in return instruction)!\n";
140167
std::vector<GlobalVariable*>::iterator it = std::find(StringGlobalVars.begin(), StringGlobalVars.end(), GV);
141168
if(it != StringGlobalVars.end()){
169+
errs() << "WARNING : " << getGlobalStringValue(GV) << " cant't be ecnrypted (const char* directly used in return instruction)!\n";
142170
StringGlobalVars.erase(it);
143171
}
144172
}else{
@@ -153,9 +181,9 @@ void AbstractStringEncryptionPass::checkStringsCanBeEncrypted(Module &M, std::ve
153181
if(GV){
154182
ConstantDataSequential *cds = dyn_cast<ConstantDataSequential>(GV->getInitializer());
155183
if(cds){
156-
errs() << "WARNING : " << getGlobalStringValue(GV) << " cant't be ecnrypted (const char* directly used in return instruction)!\n";
157184
std::vector<GlobalVariable*>::iterator it = std::find(StringGlobalVars.begin(), StringGlobalVars.end(), GV);
158185
if(it != StringGlobalVars.end()){
186+
errs() << "WARNING : " << getGlobalStringValue(GV) << " cant't be ecnrypted (const char* directly used in return instruction)!\n";
159187
StringGlobalVars.erase(it);
160188
}
161189
}
@@ -186,9 +214,9 @@ void AbstractStringEncryptionPass::checkStringsCanBeEncrypted(Module &M, std::ve
186214
if(GV){
187215
ConstantDataSequential *cds = dyn_cast<ConstantDataSequential>(GV->getInitializer());
188216
if(cds){
189-
errs() << "WARNING : " << getGlobalStringValue(GV) << " cant't be ecnrypted (const char* directly used in return instruction)!\n";
190217
std::vector<GlobalVariable*>::iterator it = std::find(StringGlobalVars.begin(), StringGlobalVars.end(), GV);
191218
if(it != StringGlobalVars.end()){
219+
errs() << "WARNING : " << getGlobalStringValue(GV) << " cant't be ecnrypted (const char* directly used in return instruction)!\n";
192220
StringGlobalVars.erase(it);
193221
}
194222
}
@@ -210,9 +238,9 @@ void AbstractStringEncryptionPass::checkStringsCanBeEncrypted(Module &M, std::ve
210238
if(GV){
211239
ConstantDataSequential *cds = dyn_cast<ConstantDataSequential>(GV->getInitializer());
212240
if(cds){
213-
errs() << "WARNING : " << getGlobalStringValue(GV) << " cant't be ecnrypted (const char* directly used in return instruction)!\n";
214241
std::vector<GlobalVariable*>::iterator it = std::find(StringGlobalVars.begin(), StringGlobalVars.end(), GV);
215242
if(it != StringGlobalVars.end()){
243+
errs() << "WARNING : " << getGlobalStringValue(GV) << " cant't be ecnrypted (const char* directly used in return instruction)!\n";
216244
StringGlobalVars.erase(it);
217245
}
218246
}
@@ -221,47 +249,6 @@ void AbstractStringEncryptionPass::checkStringsCanBeEncrypted(Module &M, std::ve
221249
}
222250
}
223251
}
224-
225-
// I don't know how to handle this case :
226-
// int main(){
227-
// const char *test[] = { "item0", "item1", "item2", "item3", "item4"};
228-
// printf("%s\n", test[3]);
229-
// return 0;
230-
// }
231-
// do not encrypt those strings ...
232-
// @TODO : find a way to handle this case and remove this code
233-
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
234-
for (Function::iterator bb = I->begin(), e = I->end(); bb != e; ++bb) {
235-
for (BasicBlock::iterator inst = bb->begin(); inst != bb->end(); ++inst) {
236-
if(llvm::MemCpyInst* memcpyInst = dyn_cast<llvm::MemCpyInst>(inst)){
237-
if (llvm::ConstantExpr *constExpr = llvm::dyn_cast<llvm::ConstantExpr>(memcpyInst->getArgOperand(1))){
238-
if(llvm::CastInst* castInst = dyn_cast<llvm::CastInst>(constExpr->getAsInstruction())){
239-
if (GlobalVariable* global = dyn_cast<GlobalVariable>(castInst->getOperand(0))) {
240-
if (ConstantArray* array = dyn_cast<ConstantArray>(global->getInitializer())) {
241-
for(unsigned int i = 0; i < array->getNumOperands(); i++){
242-
if(ConstantExpr* ce = dyn_cast<ConstantExpr>(array->getOperand(i))){
243-
if(GetElementPtrInst *gep = dyn_cast<GetElementPtrInst>(ce->getAsInstruction())){
244-
if(GlobalVariable* gv = dyn_cast<GlobalVariable>(gep->getPointerOperand())){
245-
if(dyn_cast<ConstantDataSequential>(gv->getInitializer())){
246-
errs() << "WARNING : " << getGlobalStringValue(gv) << " won't be ecnrypted (char** encryption not fully supported!)!\n";
247-
std::vector<GlobalVariable*>::iterator it = std::find(StringGlobalVars.begin(), StringGlobalVars.end(), gv);
248-
if(it != StringGlobalVars.end()){
249-
StringGlobalVars.erase(it);
250-
}
251-
}
252-
}
253-
}
254-
}
255-
}
256-
}
257-
}
258-
}
259-
}
260-
}
261-
262-
}
263-
}
264-
}
265252
}
266253

267254
bool AbstractStringEncryptionPass::encryptString(Module &M, std::vector<GlobalVariable*>& StringGlobalVars, std::vector<GlobalVariable*>& StringGlobalVarsToDelete) {
@@ -376,61 +363,8 @@ void AbstractStringEncryptionPass::handleLoad(Module &M, LoadInst* Load) {
376363
//check if loaded pointer is global
377364
Value* ptrOp = Load->getPointerOperand();
378365
GlobalVariable *GV = dyn_cast<GlobalVariable>(ptrOp);
379-
if (GV == 0){
380-
// handle load i8* getelementptr inbounds ([X x i8]* @string, i32 0, i64 x), align 1
381-
ConstantExpr *constExpr = dyn_cast<ConstantExpr>(ptrOp);
382-
if(constExpr != 0){
383-
GetElementPtrInst* gepInst = dyn_cast<GetElementPtrInst>(constExpr->getAsInstruction());
384-
if (gepInst != 0) {
385-
//check if the string is encrypted
386-
StringRef gepOpName = gepInst->getPointerOperand()->getName();
387-
std::map<std::string, GlobalVariable*>::iterator it = StringMapGlobalVars.find(gepOpName.str());
388-
if(it != StringMapGlobalVars.end()){
389-
//get size of string
390-
ConstantDataSequential *cds = dyn_cast<ConstantDataSequential>(it->second->getInitializer());
391-
uint64_t size = cds->getNumElements();
392-
//generate IR to decrypt string
393-
Value* decryptedStr = stringDecryption(M, it->second, size, Load);
394-
std::vector<Value*> idxlist;
395-
idxlist.push_back(gepInst->getOperand(gepInst->getNumOperands() - 1));
396-
GetElementPtrInst* newGep = GetElementPtrInst::Create(decryptedStr, ArrayRef<Value*>(idxlist), "", Load);
397-
LoadInst* newload = new LoadInst(newGep, "", false, 8, Load);
398-
//replace current load with the decryption code
399-
Load->replaceAllUsesWith(newload);
400-
InstructionToDel.push_back(Load);
401-
}else{
402-
// handle load i8** getelementptr inbounds ([X x i8*]* @string_array, i32 0, i64 x), align 8
403-
if (GlobalVariable* global = dyn_cast<GlobalVariable>(gepInst->getPointerOperand())) {
404-
if (ConstantArray* array = dyn_cast<ConstantArray>(global->getInitializer())) {
405-
Constant* c = array->getAggregateElement(dyn_cast<ConstantInt>(gepInst->getOperand(2))->getZExtValue());
406-
ConstantExpr* ce = dyn_cast<ConstantExpr>(c);
407-
if(ce){
408-
GetElementPtrInst *gepElementFromArray = dyn_cast<GetElementPtrInst>(ce->getAsInstruction());
409-
if(gepElementFromArray){
410-
StringRef gepOpName = gepElementFromArray->getPointerOperand()->getName();
411-
std::map<std::string, GlobalVariable*>::iterator it = StringMapGlobalVars.find(gepOpName.str());
412-
if(it != StringMapGlobalVars.end()){
413-
//get size of string
414-
ConstantDataSequential *cds = dyn_cast<ConstantDataSequential>(it->second->getInitializer());
415-
uint64_t size = cds->getNumElements();
416-
//generate IR to decrypt string
417-
Value* decryptedStr = stringDecryption(M, it->second, size, Load);
418-
std::vector<Value*> idxlist;
419-
idxlist.push_back(gepElementFromArray->getOperand(gepElementFromArray->getNumOperands() - 1));
420-
GetElementPtrInst* newGep = GetElementPtrInst::Create(decryptedStr, ArrayRef<Value*>(idxlist), "", Load);
421-
//replace current load with the decryption code
422-
Load->replaceAllUsesWith(newGep);
423-
InstructionToDel.push_back(Load);
424-
}
425-
}
426-
}
427-
}
428-
}
429-
}
430-
}
431-
}
366+
if (GV == 0)
432367
return;
433-
}
434368

435369
//check if loaded pointer is constant
436370
Constant* c = GV->getInitializer();

0 commit comments

Comments
 (0)