周口| 广丰| 高邑| 巴林左旗| 红原| 巴马| 襄汾| 枝江| 海门| 镇康| 安丘| 商城| 阿勒泰| 肥乡| 朝阳市| 黑河| 察哈尔右翼后旗| 抚松| 泉港| 大方| 泸州| 孝感| 太原| 英吉沙| 滦县| 德惠| 贡山| 永登| 韶山| 海盐| 蓬安| 和顺| 开原| 云浮| 永登| 澄江| 铁山| 汝南| 临桂| 乳源| 博爱| 嵊泗| 黄埔| 兴国| 铜山| 贵定| 苗栗| 丰县| 宁安| 卓尼| 东辽| 大龙山镇| 江城| 蒲城| 礼县| 龙井| 甘泉| 吴江| 武陵源| 黑河| 石阡| 沧源| 金平| 潼南| 章丘| 武定| 贵溪| 青浦| 天等| 新县| 五大连池| 乌拉特前旗| 禹城| 栖霞| 阜新市| 长阳| 青岛| 达尔罕茂明安联合旗| 兰坪| 山亭| 宣化区| 黄冈| 龙川| 海沧| 兴县| 天等| 杞县| 堆龙德庆| 大姚| 蕲春| 丁青| 马龙| 新会| 赤城| 江城| 瑞丽| 沙雅| 文县| 安国| 安康| 新源| 融水| 景宁| 玛沁| 全椒| 公主岭| 兴城| 长白山| 民丰| 聊城| 秦皇岛| 塘沽| 淅川| 察哈尔右翼前旗| 五家渠| 内江| 略阳| 余江| 蒲城| 青岛| 化州| 文登| 奉新| 无极| 嘉禾| 波密| 南川| 拜泉| 凤翔| 罗城| 嵊泗| 顺昌| 朔州| 双鸭山| 新沂| 延安| 泗洪| 临高| 保靖| 黔西| 滨海| 祁东| 北流| 龙山| 台山| 旬邑| 北碚| 红古| 葫芦岛| 南漳| 泉州| 内丘| 巨野| 中宁| 宿松| 南郑| 峨眉山| 枝江| 开江| 青川| 赤峰| 麻栗坡| 靖西| 望城| 万荣| 潜江| 临县| 吉安县| 华宁| 阜阳| 湘阴| 宽城| 许昌| 井研| 维西| 古田| 武功| 永城| 黄龙| 柯坪| 九龙| 安顺| 西山| 孝感| 嫩江| 湖口| 安西| 肃南| 南雄| 阳江| 黄陂| 彭水| 浦北| 郁南| 东阳| 洪雅| 罗田| 武隆| 五华| 嵊州| 拉萨| 漾濞| 秦安| 基隆| 安龙| 马祖| 安康| 梁河| 相城| 子长| 蒙山| 宿州| 乌海| 同心| 宣恩| 淄博| 祁阳| 临武| 调兵山| 卓资| 海晏| 济阳| 铜陵县| 兰州| 阳山| 呼玛| 深州| 乌审旗| 德庆| 定州| 公主岭| 金州| 利川| 东阿| 攸县| 普洱| 大足| 洛浦| 漳平| 隆昌| 潼南| 云集镇| 奎屯| 德令哈| 井冈山| 曲靖| 蒙阴| 平陆| 石屏| 祁连| 金坛| 定西| 山丹| 岑溪| 平利| 伊宁市| 苏尼特右旗| 宁城| 明溪| 武定| 漳平| 彰武| 新平| 莎车| 威尼斯人网上注册

红旗砖厂

2018-04-24 16:17 来源:大河网

  红旗砖厂

  凯斯线上娱乐据了解,四川音乐季活动实施方案出炉,提出以成都为核心,以甘阿凉三州为重点,其他市州联动发展的1+3+N四川音乐季活动模式,通过开展四川音乐季活动,进一步扶持四川省优秀音乐原创作品、打造特色音乐季品牌、培育市场主体、延伸产业链、创新文化服务模式,推动跨界融合发展,推进音乐产业的提档升级,丰富人民群众精神生活,充分发挥音乐产业对四川经济结构转型,统筹推进全省经济、政治、文化、社会和生态文明建设中的重要作用。后为消除痕迹躲避追踪,仲某尝试使用了该网站的私密钱包功能,将10枚比特币投入私密钱包内,但该功能后被证实为钓鱼网站,存入的10枚比特币已无法找回。

这是一个关于爱的不老传说。习近平总书记指出,全面建成小康社会,绝不能出现富者累巨万,而贫者食糟糠的现象。

  3天时间里,将有摇滚老炮、音乐新势力、嘻哈、电音等知名音乐人、乐队携手4组天府麻辣笑星马维维、卢匕李阳、万喜、王二莽强势助阵。魏铭淇说,在每天的工作中她都努力做到最好,希望我能用声音架起警方和群众之间沟通的桥梁。

  省物价局会同省卫生和计划生育委员会、省人力资源和社会保障厅、省中医药管理局管理部、省属及中央、省直单位(企业)所属公立医疗机构和在长部队(武警)公立医院医疗服务价格。同时,各市(州)、长白山管委会、梅河口市、公主岭市价格主管部门会同同级卫生计生、人力资源社会保障、中医药部门负责制定和调整本地区内市、区、县属及市、县直单位(企业)所属公立医疗机构和当地部队(武警)公立医院医疗服务价格。

今天白天,全省多云有时晴,通化、白山、长白山保护区有雨夹雪或小雨。

  与此同时,俄罗斯经济发展部表示,俄方并未同中方一道提出这一议案,只是世贸组织秘书处将该议题合二为一。

  三、骨灰级技术专家的鉴定方法1、用近红外透射光谱与气相色谱分析相结合的方式鉴定真假酒。该条款授权美国贸易代表可对他国的不合理或不公正贸易做法发起调查,并可在调查结束后建议美国总统实施单边制裁,包括撤销贸易优惠、征收报复性关税等。

  鉴于此,特授予余真2017陈子昂年度青年诗人奖。

  现场,招聘单位的揽才之争可谓激烈。中方已经做好准备,有实力捍卫国家利益,希望双方保持理性,共同努力,维护中美经贸关系总体稳定的大局。

  包括初创企业补贴、小额担保贷款贴息、灵活就业社会保险补贴、企业吸纳社会保险补贴、公益性岗位补贴、求职创业补贴、就业见习补贴、就业扶贫车间一次性奖补、职业培训补贴共9项。

  美高梅官方赌场广东勃朗特智能装备股份有限公司东北区市场总监畅游告诉记者,目前该公司智能机器人的订单已经排到了2019年。

  国家预算对公共服务的范围、深度进一步拓展,健康中国、优质教育、住房保障等新需求都列入财政保障重点。曾经用碎发作画那位美发师太有才了!画得这么好,我都不忍心刷车了!于先生笑着说。

  吉祥坊体育直播 朋友圈都在这里买的 永相逢娱乐

  红旗砖厂

 
责编:

吾爱破解 - LCG - LSG |安卓破解|病毒分析|破解软件|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3665|回复: 43
上一主题 下一主题

红旗砖厂

  [复制链接]
跳转到指定楼层
楼主
发表于 2018-4-9 15:04 | 只看该作者 回帖奖励 |倒序浏览
本帖最后由 NavilleZhang 于 2018-4-10 13:11 编辑

我决定把自留地里的一些文章搬运过来,纯给新手入门使用。稳定的开源混淆请参见 HikariObfuscator/Hikari
注:如同另一篇一样,这只是个演示向的教学,这个实现的问题会在末尾写出。实际使用请直接使用Hikari的实现。 原来的帖子下面还有一些其他的讨论,来玩呀。

零基础的入门贴的入门指南(如果你完全没有接触过LLVM的话这是必读) : http://www.alonemonkey.com.cfporn.com/2017/06/02/writing-an-llvm-pass/

前置要求

  • 对C++/C的入门知识
  • 高中及以上的英语水平
  • 一台电脑
  • 对命令行的基础使用
  • 对垃圾代码的忍耐能力
  • 会用Google
  • 会下载安装编译LLVM
葡京国际城 他开车来到四川街一个朋友的店铺,就把车停在一家美发店附近的停车位上。

这篇文章来源于我在实现自己的产品级混淆器中遇到的现有实现方案的各种问题,编写过程中可能会出现各种中英文混用导致无法Google到相关信息,另外我是个非常糟糕的老师,文章的各种问题还望海涵。

基础知识

  • 每个源码文件(大致上)对应一个翻译单元(Translation Unit), LLVM体系中每个Module对应一个翻译单元
  • Module是LLVM中间表示的最外层封装,所有的函数,变量,元数据等等全部封装在对应的Module中
  • (几乎)所有跟LLVM中间表示有关的数据类型都继承自llvm::Value 下文中所有的值指代的都是该类所有子类的统称
  • 字符串在LLVM中间表示里用一个常数数组实现。(但有对应的基于字符串的构造方法)
  • 每个函数由一个或多个基本块组成,每个基本块有一个结束指令用于改变控制流。调用其他函数,跳转至其他基本块,返回void或其他值的指令都属于此列。参见 LLVM Language Reference Manual

实现设计

设计上我们搜索所有函数内对全局变量的调用,判断是否为常数数组,如是则在函数的起始位置插入解密函数,在函数的结尾插入加密函数。这点上优于现有的上海交通大学密码与计算机安全实验室的实现方案Armariris,对于该方案的详细分析可以参见我的博客

正文

首先我们导出一份任意包含字符串的源码的中间表示供参考。
我们使用的源码是如下我手动构造的示例文件:

#import <Foundation/Foundation.h>
#import <dlfcn.h>
#import <objc/runtime.h>
static char* foo1="GlobalVariable";
int main(){
  printf("你好世界");
  NSLog(@"你好");
  return 0;
}

在我的macOS上使用Apple的clang:

clang -S -emit-llvm SOURCE.mm

产生了如下的LLVM中间表示:

; ModuleID = 'hw.m'
source_filename = "hw.m"
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.13.0"

%struct.__NSConstantString_tag = type { i32*, i32, i8*, i64 }

@.str = private unnamed_addr constant [13 x i8] c"\E4\BD\A0\E5\A5\BD\E4\B8\96\E7\95\8C\00", align 1
@__CFConstantStringClassReference = external global [0 x i32]
@.str.1 = private unnamed_addr constant [3 x i16] [i16 20320, i16 22909, i16 0], section "__TEXT,__ustring", align 2
@_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 2000, i8* bitcast ([3 x i16]* @.str.1 to i8*), i64 2 }, section "__DATA,__cfstring", align 8

; Function Attrs: noinline optnone ssp uwtable
define i32 home.php?mod=space&uid=443615 #0 {
  %1 = alloca i32, align 4
  store i32 0, i32* %1, align 4
  %2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str, i32 0, i32 0))
  notail call void (i8*, ...) @NSLog(i8* bitcast (%struct.__NSConstantString_tag* @_unnamed_cfstring_ to i8*))
  ret i32 0
}

declare i32 @printf(i8*, ...) #1

declare void @NSLog(i8*, ...) #1

attributes #0 = { noinline optnone ssp uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6}
!llvm.ident = !{!7}

!0 = !{i32 1, !"Objective-C Version", i32 2}
!1 = !{i32 1, !"Objective-C Image Info Version", i32 0}
!2 = !{i32 1, !"Objective-C Image Info Section", !"__DATA,__objc_imageinfo,regular,no_dead_strip"}
!3 = !{i32 4, !"Objective-C Garbage Collection", i32 0}
!4 = !{i32 1, !"Objective-C Class Properties", i32 64}
!5 = !{i32 1, !"wchar_size", i32 4}
!6 = !{i32 7, !"PIC Level", i32 2}
!7 = !{!"clang version 6.0.0 (trunk 318965) (llvm/trunk 318964)"}

基础知识: LLVM的函数分为declare和definition两种。如上所示,declare指的是实现在当前翻译单元外的函数,definition反之。

有了这些知识,接下来我们先搭建我们的Pass的大致结构.注意KeyMap是我们用于存储变量和对应Key的映射表:

/*
*  LLVM StringEncryption Pass
*  https://mayuyu.io
*  GPL V3 Licensed
*/
#include "llvm/IR/Constants.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Value.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdlib>
#include <iostream>
#include <map>
#include <set>
#include <string>
/*
  Unlike Armariris which inject decrytion code at llvm.global_ctors.
  We try to find the containing Function of Users referencing our string GV.
  Then we search for terminators.
  We insert decryption code at begining or the function and encrypt it back at
  terminators

  For Users where we cant find a Function, we then inject decryption codes at
  ctors
*/
/*
Status: Currently we only handle strings passed in directly.
GV strings are not properly handled
*/
using namespace llvm;
using namespace std;
namespace llvm {
struct StringEncryption : public ModulePass {
  static char ID;
  map<GlobalVariable * /*Value*/, Constant * /*Key*/>
      keymap; // Map GV to keys for encryption
  StringEncryption() : ModulePass(ID) {}
  StringRef getPassName() const override {
    return StringRef("StringEncryption");
  }
  bool runOnModule(Module &M) override {
    // in runOnModule. We simple iterate function list and dispatch functions
    // to handlers
    for (Module::iterator iter = M.begin(); iter != M.end(); iter++) {
      Function &F = *iter;
      HandleFunction(&F);
    }
    EncryptGVs(M);
    return true;
  } // End runOnModule
};
Pass *createStringEncryptionPass() { return new StringEncryption(); }
} // namespace llvm

char StringEncryption::ID = 0;
static RegisterPass<StringEncryption> X("strenc", "StringEncryption");

这里我们创建了一个ModulePass,顾名思义运行在每个Module之上。LLVM IR的Pass的入口点是对应的 runOnXXX 函数,这里即 runOnModule, 并使用Module的迭代器来遍历所有的函数,并将对应的函数分发给HandleFunction() 方法。 接下来我们开始实现handleFunction函数,这个函数的主要作用是分析函数的相关信息并作处理,也就是所有的重要工作的所在地 。首先我们使用 Function::isDeclaration 来过滤掉所有的declare函数。
然后我们依次遍历函数->基本块->指令->指令的参数:  

set<GlobalVariable *> Globals;
set<Instruction *> Terminators;
for (BasicBlock &BB : *Func) {
      for (Instruction &I : BB) {
        if (ReturnInst *TI = dyn_cast<ReturnInst>(&I)) {
          Terminators.insert(TI);
        }
        for (Value *Op : I.operands()) {
          if (GlobalVariable *G = dyn_cast<GlobalVariable>(Op)) {
            Globals.insert(G);
          }
        }
      }
    }

但,这样的方式并不会收集到我们所用示例中的所有字符串,为什么呢?让我们倒回去看一下中间表示:

%2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str, i32 0, i32 0))
notail call void (i8*, ...) @NSLog(i8* bitcast (%struct.__NSConstantString_tag* @_unnamed_cfstring_ to i8*))

这里对NSLog传递的参数为一个BitCast的常量表达式. LLVM使用的是非常严格的类型系统。比高级编程语言的类型检查更严格,例如,一个装有五个32位整数的数组和一个装有六个32位整数的数组在LLVM的类型体系中是不一样的,对他们的互相替换被视为非法操作。而BitCast指令/常量表达式就是LLVM的强制类型转换指令。在上面的例子中将类型为struct.__NSConstantString_tag指针的全局变量@_unnamed_cfstring_转换成了i8类型的指针,符合NSLog的函数声明。

而printf使用的GEP是LLVM中较为复杂难以理解的一条指令,简单的说GEP的作用是计算地址,详细的解释请参见上面的官方文档和The Often Misunderstood GEP Instruction

无论如何,在增加对应的处理之后我们的代码变成了:

    for (BasicBlock &BB : *Func) {
      for (Instruction &I : BB) {
        if (ReturnInst *TI = dyn_cast<ReturnInst>(&I)) {
          Terminators.insert(TI);
        }
        for (Value *Op : I.operands()) {
          if (GlobalVariable *G = dyn_cast<GlobalVariable>(Op)) {
            Globals.insert(G);
          } else if (Constant *C = dyn_cast<Constant>(Op)) {
            Constant *stripped = C->stripPointerCasts();
            if (GlobalVariable *GV = dyn_cast<GlobalVariable>(stripped)) {
              Globals.insert(GV);
              continue;
            }
          }
        }
      }
    }

接下来我们需要过滤掉不能加密的函数,比如说外部的全局变量,不是正确类型的全局变量,ObjC的元信息,LLVM的元信息等都属于此列。
直接上代码吧没啥好详解的:

if (GV->hasInitializer() &&
          GV->getSection() != StringRef("llvm.metadata") &&
          GV->getSection().find(StringRef("__objc")) == string::npos &&
          GV->getName().find("OBJC") == string::npos) {
        if (isa<ConstantDataSequential>(GV->getInitializer()) || isa<ConstantStruct>(GV->getInitializer())) {
          GV->setConstant(false);
          ConstantDataSequential *CDS =NULL;
          if(isa<ConstantDataSequential>(GV->getInitializer())){
            CDS=dyn_cast<ConstantDataSequential>(GV->getInitializer());
          }
          else if(isa<ConstantStruct>(GV->getInitializer()) && Func->getParent()->getTypeByName("struct.__NSConstantString_tag")!=NULL){
            ConstantStruct* CS=dyn_cast<ConstantStruct>(GV->getInitializer());
            if(CS->getType()!=Func->getParent()->getTypeByName("struct.__NSConstantString_tag")){
              continue;
            }
            GV=cast<GlobalVariable>(CS->getOperand(2)->stripPointerCasts());
            CDS=cast<ConstantDataSequential>(GV->getInitializer());
          }
          else{
            continue;
          }
Type *memberType = CDS->getElementType();
          // Ignore non-IntegerType
          if (!isa<IntegerType>(memberType)) {
            continue;
          }
}

这里我们除了过滤之外,还负责了从struct.__NSConstantString_tag 结构体中提取真实的字符串常量,判断数组所包含的数据类型是不是整数的操作。 接下来我们开始生成对应的解密Key.这里的代码比较屎,欢迎C++大神提点:

if (keymap.find(GV) == keymap.end()) {
            // No Existing Key Found.
            // Perform injection
            if (intType == Type::getInt8Ty(GV->getParent()->getContext())) {
              vector<uint8_t> keys;
              for (unsigned i = 0; i < CDS->getNumElements(); i++) {
                keys.push_back(cryptoutils->get_uint8_t());
              }
              Constant *KeyConst = ConstantDataVector::get(
                  GV->getParent()->getContext(), ArrayRef<uint8_t>(keys));
              keymap[GV] = KeyConst;
            } else if (intType ==
                       Type::getInt16Ty(GV->getParent()->getContext())) {
              vector<uint16_t> keys;
              for (unsigned i = 0; i < CDS->getNumElements(); i++) {
                keys.push_back(cryptoutils->get_uint16_t());
              }
              Constant *KeyConst = ConstantDataVector::get(
                  GV->getParent()->getContext(), ArrayRef<uint16_t>(keys));
              keymap[GV] = KeyConst;
            } else if (intType ==
                       Type::getInt32Ty(GV->getParent()->getContext())) {
              vector<uint32_t> keys;
              for (unsigned i = 0; i < CDS->getNumElements(); i++) {
                keys.push_back(cryptoutils->get_uint32_t());
              }
              Constant *KeyConst = ConstantDataVector::get(
                  GV->getParent()->getContext(), ArrayRef<uint32_t>(keys));
              keymap[GV] = KeyConst;
            } else if (intType ==
                       Type::getInt64Ty(GV->getParent()->getContext())) {
              vector<uint64_t> keys;
              for (unsigned i = 0; i < CDS->getNumElements(); i++) {
                keys.push_back(cryptoutils->get_uint64_t());
              }
              Constant *KeyConst = ConstantDataVector::get(
                  GV->getParent()->getContext(), ArrayRef<uint64_t>(keys));
              keymap[GV] = KeyConst;
            } else {
              errs() << "Unsupported CDS Type\n";
              abort();
            }
          }

这样,和Armariris不同的是,我们为每一项都生成了一组对应的Key. 接下来我们在函数的第一个基本块(EntryBlock)寻找适合插入指令的没有Phi Node等杂项的位置。(实际上函数的EntryBlock不能也不会有PhiNode,具体意思我会在末尾补充)
使用 IRBuilder<> IRB(Func->getEntryBlock().getFirstNonPHIOrDbgOrLifetime ()); 创建IRBuilder, IRBuilder是LLVM提供的方便指令插入的助手模版类。
我们首先创造一个GEP来获得原始变量的指针,然后将其从原来的[数量 x 单个字符大小]BitCast成我们需要的类型。最后加载,完成异或操作后写回原始变量。在Terminator处的处理同理。 注意这是一个Hack并且只能在MinSizeRelease下使用才不会触发Assert。
BinaryOperator按照规矩是只接受Vector的,而clang前端生成的是Array。Again,稳定的实现请参照Hikari的源码

          Value *zero = ConstantInt::get(
              Type::getInt32Ty(GV->getParent()->getContext()), 0);//因为我们从头开始加密。所以gep的索引都是0
          Value *zeroes[] = {zero,zero};
          Value *GEP = IRB.CreateInBoundsGEP(GV, zeroes);
          //BinaryOperations don't take CDAs,only CDVs
          //FIXME: Figure out if CDA and CDV has same mem layout
          Value* BCI=IRB.CreateBitCast(GEP,keymap[GV]->getType()->getPointerTo());
          LoadInst *LI = IRB.CreateLoad(BCI);//ArrayType
          Value *XOR = IRB.CreateXor(LI, keymap[GV]);
          IRB.CreateStore(XOR, BCI);
          for (Instruction *I : Terminators) {
            IRBuilder<> IRB(I);
            Value *zero = ConstantInt::get(
                Type::getInt32Ty(GV->getParent()->getContext()), 0);
            Value *zeroes[] = {zero, zero};
            Value *GEP = IRB.CreateInBoundsGEP(GV, zeroes);
            Value* BCI=IRB.CreateBitCast(GEP,keymap[GV]->getType()->getPointerTo());
            LoadInst *LI = IRB.CreateLoad(BCI);//ArrayType
            Value *XOR = IRB.CreateXor(LI, keymap[GV]);
            IRB.CreateStore(XOR,BCI);
          }

最后,我们在完成后调用我们的EncryptGV。 我们遍历之前创建的映射表。对于unicode类型的字符串编译器默认会放在 __TEXT这个不可写的段,导致我们的XOR触发操作系统保护异常,这需要我们进行修复:   

  void EncryptGVs(Module &M){
    // We've done Instruction Insertation
    // Perform GV Encrytion
    for (map<GlobalVariable *, Constant *>::iterator it = keymap.begin();
         it != keymap.end(); ++it) {
      GlobalVariable *GV = it->first;
      assert(GV->hasInitializer() && "Encrypted GV doesn't have initializer");
      ConstantDataSequential *Key = cast<ConstantDataSequential>(it->second);
      ConstantDataSequential *GVInitializer =
          cast<ConstantDataSequential>(GV->getInitializer());
      assert(Key->getNumElements() == GVInitializer->getNumElements() &&
             "Key and String size mismatch!");
      assert(Key->getElementType() == GVInitializer->getElementType() &&
                    "Key and String type mismatch!");
      Type *memberType = Key->getElementType();
      IntegerType *intType = cast<IntegerType>(memberType);
      //Fixup GV sections otherwise we might fall into __TEXT and get a EXC_i386_GPFLT
      //or other platform's equivalent
      if(GV->getSection().find("__TEXT")!=string::npos){
        GV->setSection("__DATA,__const");
      }

      if (intType == Type::getInt8Ty(M.getContext())) {
        vector<uint8_t> Encrypted;
        for (unsigned i = 0; i < Key->getNumElements(); i++) {
          uint64_t K = Key->getElementAsInteger(i);
          uint64_t S = GVInitializer->getElementAsInteger(i);
          Encrypted.push_back(K^S);
        }
        Constant* newInit=ConstantDataArray::get(M.getContext(),ArrayRef<uint8_t>(Encrypted));
        GV->setInitializer(newInit);
      }
      else if (intType == Type::getInt16Ty(M.getContext())) {
        vector<uint16_t> Encrypted;
        for (unsigned i = 0; i < Key->getNumElements(); i++) {
          uint64_t K = Key->getElementAsInteger(i);
          uint64_t S = GVInitializer->getElementAsInteger(i);
          Encrypted.push_back(K ^ S);
        }
        Constant* newInit=ConstantDataArray::get(M.getContext(),ArrayRef<uint16_t>(Encrypted));
        GV->setInitializer(newInit);
      } else if (intType == Type::getInt32Ty(M.getContext())) {
        vector<uint32_t> Encrypted;
        for (unsigned i = 0; i < Key->getNumElements(); i++) {
          uint64_t K = Key->getElementAsInteger(i);
          uint64_t S = GVInitializer->getElementAsInteger(i);
          Encrypted.push_back(K ^ S);
        }
        Constant* newInit=ConstantDataArray::get(M.getContext(),ArrayRef<uint32_t>(Encrypted));
        GV->setInitializer(newInit);
      } else if (intType == Type::getInt64Ty(M.getContext())) {
        vector<uint64_t> Encrypted;
        for (unsigned i = 0; i < Key->getNumElements(); i++) {
          uint64_t K = Key->getElementAsInteger(i);
          uint64_t S = GVInitializer->getElementAsInteger(i);
          Encrypted.push_back(K ^ S);
        }
        Constant* newInit=ConstantDataArray::get(M.getContext(),ArrayRef<uint64_t>(Encrypted));
        GV->setInitializer(newInit);

      } else {
        errs() << "Unsupported CDS Type\n"<<*intType<<"\n";
        abort();
      }
      errs()<<"Rewritten GlobalVariable:"<<*GVInitializer<<" To:"<<*(GV->getInitializer())<<"\n";
    }
  }

收尾

  • PhiNode指的是一个代表的数值随着控制流的变化而变化的值。例如PhiNode允许当控制流从基本块A跳转时代表1,基本块b跳转时代表2.
  • 我们这里的实现实际上非常简陋,例如当一个全局变量引用另一个文本全局变量时我们没有处理会导致编译失败。这部分需要单独处理并在llvm.global_ctors 中解密,类似于Theos的 %ctor或者__attribute__((constructor))  
  • 这实际上同样不是最好的实现方式。 对于在堆上保存着使用的情况。这种实现返回时会导致字符串被加密回去。

Demo

源文件腾磁盘空间的时候删了。上个当时的截图吧 http://7xibfi.com1.z0.glb.clouddn.com.cfporn.com/uploads/default/original/2X/2/2f1e2d00cca8ee2c51ca05717c2598c36856a747.JPG


免费评分

参与人数 27吾爱币 +29 热心值 +26 收起 理由
ddtsatan + 1 + 1 热心回复!
fungus + 1 谢谢@Thanks!
两桶泡面 + 1 热心回复!
cyril2017 + 1 + 1 用心讨论,共获提升!
xyuetao + 1 + 1 谢谢@Thanks!
zjc841104 + 1 + 1 热心回复!
z17v2ui + 1 + 1 喜欢这种零基础的教程
sunnylds7 + 1 + 1 热心回复!
W丶零度 + 1 + 1 我很赞同!
七情哥哥 + 1 用心讨论,共获提升!
a5606495 + 1 + 1 热心回复!
cjhm + 1 + 1 感谢张总的分享!!!
Nicklobin + 1 + 1 张总威武,开了眼界,之前一直很懵逼。
kbvsfm + 1 + 1 谢谢@Thanks!
pk8900 + 1 + 1 一个没接触过的领域,感谢楼主分享。
wang754782072 + 1 + 1 谢谢@Thanks!
cr7890 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
羽月莉音 + 1 + 1 谢谢@Thanks!
dibh10 + 1 + 1 用心讨论,共获提升!
初亦泽 + 3 + 1 谢谢你
jixun66 + 3 + 1 感谢作者,希望有更多 LLVM 相关内容。
Vsir + 1 + 1 谢谢@Thanks!
孤骜 + 1 + 1 谢谢@Thanks!
wmsuper + 1 + 1 用心讨论,共获提升!
很快再相见123 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Ravey + 1 + 1 谢谢@Thanks!
sushangyu + 1 + 1 虽然什么都看都不懂,但是感觉高大尚

查看全部评分

本帖被以下淘专辑推荐:

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子分类或者标题加上【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

推荐
发表于 2018-4-10 13:32 | 只看该作者
        谢谢老师无私的奉献

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子分类或者标题加上【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

推荐
发表于 2018-4-10 09:34 | 只看该作者

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子分类或者标题加上【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

板凳
发表于 2018-4-9 15:51 | 只看该作者

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子分类或者标题加上【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

报纸
发表于 2018-4-9 16:01 | 只看该作者
支持张总

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子分类或者标题加上【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

地板
发表于 2018-4-9 16:18 | 只看该作者
好像很厉害,但是没看懂

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子分类或者标题加上【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

7#
发表于 2018-4-9 17:15 | 只看该作者
谢谢楼主的分享

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子分类或者标题加上【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

8#
发表于 2018-4-9 17:47 | 只看该作者
感谢分享.

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子分类或者标题加上【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

9#
发表于 2018-4-9 19:07 | 只看该作者
很精彩,认真学习了。感谢分享

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子分类或者标题加上【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

10#
发表于 2018-4-9 20:38 | 只看该作者
认真学习

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子分类或者标题加上【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

11#
发表于 2018-4-10 00:11 | 只看该作者
谢谢楼主分享,希望继续更新

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子分类或者标题加上【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

12#
发表于 2018-4-10 00:42 | 只看该作者
感谢楼主的分享,很精彩,认真学习了

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子分类或者标题加上【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则


免责声明:
吾爱破解所发布的一切破解补丁、注册机和注册信息及软件的解密分析文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。

Mail To:Service@52PoJie.Cn

快速回复 收藏帖子 返回列表 搜索

吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2018-4-19 13:38

Powered by Discuz!

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表
山东早餐加盟 早餐豆浆加盟 早餐加盟店 早餐加盟店 早点小吃加盟连锁
春光早餐工程加盟 早餐粥店加盟 营养早点加盟 早点夜宵加盟 早餐豆腐脑加盟
早餐加盟项目 广式早点加盟 健康早餐店加盟 杨国福麻辣烫加盟 早餐
特色早餐店加盟 早餐面馆加盟 正宗早点加盟 流动早餐加盟 舒心早餐加盟
百度