风扫春残雪 发表于 2020-7-6 23:00

(抛砖引玉)x86反-乱序/膨胀处理脚本

本帖最后由 风扫春残雪 于 2020-7-6 23:06 编辑

分析了两天CM区一个乱序的(https://www.52pojie.cn/thread-1213289-1-1.html),感觉非常有意思。
虽然最后还是没能坚持下来,但顺手写了点儿程序,未来不管是分析同类乱序,还是壳内的乱序,想来都应该有用。发上来和大家一起学习交流
(大佬轻拍,主要是给我等萌新复习姿势用……这个方向细分水太深了)

这个帖子大概分为几部分
1. 反乱序处理
2. 反膨胀处理
3. 脚本说明

1. 乱序处理
这几天研究了很多怎么把一段代码进行正向乱序的帖子,我就不再班门弄斧了,参见
https://bbs.pediy.com/thread-96640.htm
https://bbs.pediy.com/thread-180456.htm

http://bbs.pediy.com/showthread.php?t=49923

http://bbs.pediy.com/showthread.php?t=155878
http://bbs.pediy.com/showthread.php?t=155215   (特别推荐)

总得来说,就是把一大段代码分割成不同的小部分,再通过跳转互相连接起来


对乱序的代码最好的方式是动态记录,即通过脚本把单步执行的结果记录下来,或者记录关键位置的寄存器,结合静态分析进行拼接
实际上,在一些高强度的壳里边,这基本是唯一的分析方式。因为push/ret的立即数会被代码膨胀保护起来。然而拿不到顺序的程序,又很难进行反混淆
动态记录/分析的好处是,哪怕程序里使用了随机数+标志位+虚拟机手段,每次的路径都不太一样,但只要有一次运行成功的,分析那一次的就可以了

这次的脚本就是通过Ollyscript的反汇编功能进行静态分析的。
静态分析的蛋疼之处是,如果遇上了一些需要依靠数值的条件跳转,可能难以理清程序的逻辑。同时遇上复杂保护下的立即数,则需要提前获取程序流程的“MAP”才能继续。不过那样的话又实际上等同于动态分析了

2. 反膨胀处理
正向实现参考
https://bbs.pediy.com/thread-223629.htm

http://bbs.pediy.com/showthread.php?t=155215 (再次安利这篇)
https://bbs.pediy.com/thread-217588.htm

水太深了,不是我这水平的菜鸡能讨论的。大概比较先进的思路是写类llvm,把膨胀的指令优化回去
我这个脚本只能处理一些低级水平的反膨胀(


3. 我的脚本

脚本分为两部分
3.1 一部分是用Ollyscript写的静态分析。论坛上很久以前有个二货写过一遍,那个也是我。这次重新入坑我又重构了一遍,加入了一些新功能。大体上没有太多变化
3.2 另一部分反膨胀,是基于手工指令进行的文本处理反膨胀。分析不同的膨胀需要加入不同的膨胀模式,这一部分是需要自己完成的
3.3 Ollyscript程序
食用方法:
1)保存为txt,
2)修改intVirtualEIP为你想开始反乱序的地址,修改SETTING_INT_LENGTH为你想进行反乱序的长度
3)OD->插件->Ollyscript->执行
4)*note: 程序里附带了一些反trick的部分,比如jejnz花指令,比如push offset/ add ,offset2,retn这样的。如果不需要请自行修改代码


var SETTING_INT_LENGTH,int_NowLength
var SETTING_INTO_CALL
var intVirtualEIP
var intCALLRetn
var intTemp
var intFlowerJMPCALL_FlagType

//setting
mov SETTING_INT_LENGTH, 500
mov SETTING_INTO_CALL, 1

//init
mov int_NowLength, 0
mov intVirtualEIP, 404520
lclr

//start
start:
    opcode intVirtualEIP
    scmp $RESULT, "E9", 2 //LONG JMP
    je OPERATION_JMP
    scmp $RESULT, "EB", 2 //SHORT JMP
    je OPERATION_SHORT_JMP
    scmp $RESULT, "C3", 2 //RET
    je OPERATION_RET

    cmp SETTING_INTO_CALL, 0
    je OPERATION_NORMAL
    //CALL
    scmp $RESULT, "E8", 2 //CALL
    je OPERATION_CALL

OPERATION_NORMAL:
    //SPECIAL DE-FLOWER FUNCTION, SHOULD BE UPDATED EVERY TIME YOU ANALYSE A NEW PROGRAM
    scmp $RESULT, "812C24",6 // sub ,xxxx
    je OPERATION_FLOWER_SUB_ESP
    scmp $RESULT, "810424",6 // add ,xxxx
    je OPERATION_FLOWER_ADD_ESP
    scmp $RESULT, "68",2 //PUSH (PUSH XXX, RET)
    je OPERATION_FLOWER_PUSH
    scmp $RESULT_1, "mov",3 //MOV REG,XXX; LEA REG,; CALL/JMP XXX
    je OPERATION_FLOWER_MOVLEACALLJMP
    scmp $RESULT_1, "je",2 // JE OFFSET + JNZ OFFSET
    je OPERATION_FLOWER_JEJNZ
   
   
NORMAL_FUNCTION:
    opcode intVirtualEIP
    itoa intVirtualEIP
    add $RESULT," : "
    log $RESULT_1, $RESULT //Log the currect command of virtual eip


    add intVirtualEIP, $RESULT_2
done:
    inc int_NowLength
    cmp int_NowLength, SETTING_INT_LENGTH
    jnz start

    ret //SCRIPT DONE

//------------------------------------
//Func:LONG JMP
OPERATION_JMP:

    itoa intVirtualEIP
    add $RESULT," : "
    //log "LONG JMP Found"
    //log $RESULT_1, $RESULT
    gci intVirtualEIP, DESTINATION //get DESTINATION of the JMP
    mov intVirtualEIP, $RESULT
    jmp done
//------------------------------------
//Func:SHORT JMP
OPERATION_SHORT_JMP:

    itoa intVirtualEIP
    add $RESULT," : "
    //log "SHORT JMP Found"
    //log $RESULT_1, $RESULT
    gci intVirtualEIP, DESTINATION //get DESTINATION of the JMP
    mov intVirtualEIP, $RESULT
    jmp done
//------------------------------------
//Func:CALL
OPERATION_CALL:
    itoa intVirtualEIP
    add $RESULT," : "
    //log "CALL Found"
    log $RESULT_1, $RESULT
    gci intVirtualEIP, DESTINATION //get DESTINATION of the CALL
    mov intCALLRetn, intVirtualEIP
    add intCALLRetn, $RESULT_2 //KEY OF THE CALL
    mov intVirtualEIP, $RESULT
    jmp done
//------------------------------------
//Func:RET
OPERATION_RET:
    itoa intVirtualEIP
    add $RESULT," : "
    //log "RET Found"
    log $RESULT_1, $RESULT
    mov intVirtualEIP, intCALLRetn
    jmp done
//------------------------------------
//Func:OPERATION_FLOWER_SUB_ESP
OPERATION_FLOWER_SUB_ESP:
    itoa intVirtualEIP
    add $RESULT," : "
    //log "FLOWER_SUB_ESP Found"
    log $RESULT_1, $RESULT
    sub intCALLRetn,
    add intVirtualEIP, $RESULT_2
    jmp done
//------------------------------------
//Func:OPERATION_FLOWER_ADD_ESP
OPERATION_FLOWER_ADD_ESP:
    itoa intVirtualEIP
    add $RESULT," : "
    //log "FLOWER_ADD_ESP Found"
    log $RESULT_1, $RESULT
    add intCALLRetn,
    add intVirtualEIP, $RESULT_2
    jmp done
//------------------------------------
//Func:OPERATION_FLOWER_PUSH
OPERATION_FLOWER_PUSH:
    mov intTemp, intVirtualEIP
    add intTemp, $RESULT_2
    mov intTemp,
    and intTemp, FF //get the lower byte
    cmp intTemp, C3 //next code is RET
    jnz NORMAL_FUNCTION
   
    itoa intVirtualEIP
    add $RESULT," : "
    //log "FLOWER_PUSH_RETN Found"
    //log $RESULT_1, $RESULT
    mov intVirtualEIP, //bypass ret

    jmp done
//------------------------------------
//Func:OPERATION_FLOWER_PUSH
OPERATION_FLOWER_PUSH:
    mov intTemp, intVirtualEIP
    add intTemp, $RESULT_2
    mov intTemp,
    and intTemp, FF //get the lower byte
    cmp intTemp, C3 //next code is RET
    jnz NORMAL_FUNCTION
   
    itoa intVirtualEIP
    add $RESULT," : "
    log "FLOWER_PUSH_RETN Found"
    log $RESULT_1, $RESULT
    mov intCALLRetn,
    add intVirtualEIP, $RESULT_2
    jmp done
//------------------------------------
//Func:OPERATION_FLOWER_MOVLEACALLJMP
OPERATION_FLOWER_MOVLEACALLJMP:
    mov intFlowerJMPCALL_FlagType, 0 //1 for call, 2 for jmp
    mov intTemp,intVirtualEIP
    add intTemp,$RESULT_2
    opcode intTemp
    scmp $RESULT_1, "lea", 3
    jnz NORMAL_FUNCTION
    add intTemp,$RESULT_2
    opcode intTemp
    scmp $RESULT_1, "call", 4
    jnz MOVLEACALLISJMP
    mov intFlowerJMPCALL_FlagType, 1
    jmp MOVLEACALLALL
MOVLEACALLISJMP:
    scmp $RESULT_1, "jmp", 3
    jnz NORMAL_FUNCTION
    mov intFlowerJMPCALL_FlagType, 2

MOVLEACALLALL:
    //NOW IT DOES
    opcode intVirtualEIP
    mov intTemp, //save the first value in intTemp
    itoa intVirtualEIP
    add $RESULT," : "
    //log "FLOWER_MOVLEAJMP Found"
    //Log $RESULT_1, $RESULT
    //log "NOP", $RESULT
    add intVirtualEIP, $RESULT_2
    opcode intVirtualEIP
    itoa intVirtualEIP
    add $RESULT," : "
    //log $RESULT_1, $RESULT
    //log "NOP", $RESULT
    add intTemp, // add the second value in intTemp
    add intVirtualEIP, $RESULT_2
    opcode intVirtualEIP
    itoa intVirtualEIP
    add $RESULT," : "
    //log $RESULT_1, $RESULT
    //log "NOP", $RESULT
    mov intVirtualEIP, intTemp
    cmp intFlowerJMPCALL_FlagType, 2 //if JMP type, GO NOW
    je done
    mov intCALLRetn, intVirtualEIP
    add intCALLRetn, $RESULT_2 //CALL retn address
    jmp done
//------------------------------------
//Func:OPERATION_FLOWER_JEJNZ
OPERATION_FLOWER_JEJNZ:
    mov intTemp, intVirtualEIP
    add intTemp, $RESULT_2
    opcode intTemp
    scmp $RESULT_1, "jnz", 3
    jnz NORMAL_FUNCTION
    gci intTemp, DESTINATION
    mov intTemp, $RESULT
    gci intVirtualEIP,DESTINATION
    cmp intTemp, $RESULT
    jnz NORMAL_FUNCTION
   
    itoa intVirtualEIP
    add $RESULT," : "
    //log "FLOWER_PUSH_JEJNZ Found"
    //log $RESULT_1, $RESULT
    log "NOP", $RESULT

    mov intVirtualEIP, intTemp
    jmp done



3.4 python反膨胀脚本

这次就写了个框架。。。基本的思路是替换膨胀的模式,不过程序显然还不太完善,具体的改进之处有:
1)不要自己手写模拟引擎了,用正则表达更香
2)对于一些固定的模式应该考虑使用启发式还原(比如通过局部的寄存器分离,来让代码“分开”;提醒重复的模式等)

食用方法:
将3.3程序的脚本运行日志右键--复制表--保存为txt

请根据分析程序,自行修改__main__部分

主要的程序接口为:
ScanAndDel_MulReg(lstAsmCodes,lstAsmFiles,intUsedRegs,lstRegs,strReplaceCode)
lstAsmCodes:

以lst形式保存的一系列膨胀模式汇编代码。函数扫描到这些相邻的代码后,将会用strReplaceCode替换
*允许使用reg1/reg2/reg3/reg4指代寄存器
*允许使用idata,不过idata的值可能是立即数,也可能是寄存器
*允许使用any,使用any时,将不会替换any对应的指令

lstAsmFiles:
open("input.txt").readlines()形式的文件内容列表,输入必须为3.3程序的结果。

intUsedRegs:
在lstAsmCodes中使用regs指代寄存器的个数


lstRegs:
在lstAsmCodes中使用regs指代哪些寄存器,默认可以使用lst_AllREGS,不过会降低脚本速度

strReplaceCode:
替换的目的指令,只能为单行




lst_AllREGS = ['eax','ebx','ecx','edx','esi','edi']

def makelstRegs(intUsedRegs, lstCurrent, lstResult, lstAllOptions):
    if (lstCurrent != []) and ((intUsedRegs == 0) or (len(lstCurrent) == len(lstAllOptions))):
      lstResult.append(lstCurrent)
      return lstCurrent
    for reg in lstAllOptions:
      if not reg in lstCurrent:
            lstNowCurrect = lstCurrent.copy()
            lstNowCurrect.append(reg)
            makelstRegs(intUsedRegs - 1, lstNowCurrect, lstResult, lstAllOptions)
    return lstResult


def debugOut(strLine):
    f = open("debug.txt",'a')
    f.write(strLine + "\n")
    print(strLine)
    f.close()
def getAddress(strLine):
    return strLine.split(":").split(" ")[-2]
def getIdata(strLine):
    strOpCode = getAllOpCode(strLine)
    if strLine.find("[") < 0:
      #mov eax,891023h
      return strOpCode.split(",")[-1]
    else:
      #lea edx,dword ptr ds:
      strOpCode = strOpCode.split("[")[-1]
      if strOpCode.find("+")>0:
            strOpCode = "+" + strOpCode.split("+")[-1]
      elif strOpCode.find("-")>0:
            strOpCode = "-" + strOpCode.split("-")[-1]
   
      strOpCode = strOpCode.replace("]","")
      return strOpCode
def getLongAddress(strLine):
    return "*"+strLine.split(":") + ": "
def getAllOpCode(strLine):
    return ":".join(strLine.split(":")).strip("\n")
def getOpCode(strLine):
    strAllOp = getAllOpCode(strLine)
    return strAllOp.split(" ")
def getOpLeftCode(strLine):
    strAllOp = getAllOpCode(strLine)
    return strAllOp.split(",")
def ScanAndDel(lstCommand, lstASMLines, regs = [], strReplaceCode = ""):
    if regs == []:
      regs = lst_AllREGS
    for reg in regs:
      lstCommandwithREG = []
      for strCommand in lstCommand:
            lstCommandwithREG.append(strCommand.replace('reg',reg).replace("idata",""))
      for index, line in enumerate(lstASMLines):
            strIdata = ""
            if line!="":
                strAddress = getAddress(line)
            if index + len(lstCommandwithREG) <= len(lstASMLines):
                line = line.strip("\n")
                flag_found = True
                for j, strCommand in enumerate(lstCommandwithREG):
                  if lstASMLines.find(strCommand) < 0:
                        flag_found = False
                        break
                  else:
                        if strCommand.find("idata") >= 0:
                            strIdata = getIdata(lstASMLines)
                if flag_found == True:
                  debugOut("Found Command %s at Line %s, reg = %s"%(str(lstCommand), strAddress, reg))
                  for j, strCommand in enumerate(lstCommand): #erase the command
                        lstASMLines = ""
                  if strReplaceCode != "":
                        strReplaceCode =strReplaceCode.replace("idata", strIdata)
                        lstASMLines = getLongAddress(line) + strReplaceCode
    return lstASMLines

def getVaildOPcode(lstASMLines, index, j):
    #get the j-th opcodes in the lstASMLines with the pointer index
    try:
      i = -1
      lines = 0
      while (i < j):
            if lstASMLines != "":
                i += 1
            lines += 1
      return lstASMLines, lines - 1, 0
    except:
      #at the end of the file
      return "",-1,-1

def ScanAndDel_MulReg(lstCommand, lstASMLines, intRegs, regs,strReplaceCode = ""):
    lst_optionRegs = makelstRegs(intRegs, [], [], regs)
   
    #debugOut("MulReg init success, regs = %s, lstlength = %s"%(regs, len(lst_optionRegs)))
    for regs in lst_optionRegs:
      lstCommandwithREG = []
      strReplaceCodewithREG = strReplaceCode
      for strCommand in lstCommand:
            for index, item in enumerate(regs):
                strCommand = strCommand.replace("reg%s"%(index+1), item)
                strReplaceCodewithREG = strReplaceCodewithREG.replace("reg%s"%(index+1), item)
            strCommand = strCommand.replace("idata","")
            lstCommandwithREG.append(strCommand)
      ilstASMLines = lstASMLines.copy()
      for index, line in enumerate(ilstASMLines):
            strIdata = ""
            lstAnyCommand = []
            if line!= "":
                strAddress = getAddress(line)
            if index + len(lstCommandwithREG) <= len(lstASMLines):
                line = line.strip("\n")
                flag_found = True
                for j, strCommand in enumerate(lstCommandwithREG): #next j VAILD opcodes
                  #if (strAddress == "4035d4"):
                  #    print(lstASMLines)
                  #    print(lstCommandwithREG)
                  if getVaildOPcode(lstASMLines, index, j) == -1: #at the end of the file
                        flag_found = False
                        break
                  if strCommand == "any":
                        str_thisline = getAllOpCode(getVaildOPcode(lstASMLines, index, j)) #避免any匹配上后缀需要匹配的命令,必须对所有any之后的command一一比对,如果比对上了,立刻丢掉
                        flag_any_avoid = True
                        for k, strCommand_any in enumerate(lstCommandwithREG):
                            if (str_thisline.find(strCommand_any) ==0 ):
                              flag_any_avoid = False
                              flag_found = False
                              break
                        if flag_any_avoid == True:
                            lstAnyCommand.append(str_thisline)
                            continue
                        else:
                            break
                        
                  if (getAllOpCode(getVaildOPcode(lstASMLines, index, j)).find(strCommand) != 0): # >0 when find 'or eax,...' in command 'xor eax,ebx'
                        flag_found = False
                        break
                  else:
                        if lstCommand.find("idata") >= 0:
                            strIdata = getIdata(getVaildOPcode(lstASMLines, index, j))
                if (flag_found == True):
                  debugOut("Found Command(MulReg) %s at Address %s(Line = %s), reg = %s, idata = %s"%(str(lstCommand), index, strAddress, regs, strIdata))
                  if strReplaceCode != "":
                        strReplaceCodewithREG = strReplaceCodewithREG.replace("idata", strIdata)
                        lstTempToWrite = getLongAddress(getVaildOPcode(lstASMLines, index, j)) + strReplaceCodewithREG
                  else:
                        lstTempToWrite = ""
                  intAny = 0
                  lstAnyToWrite = []

                  for j, strCommand in enumerate(lstCommand): #erase the command
                        if strCommand == "any":
                            lstAnyToWrite.append((index + getVaildOPcode(lstASMLines, index, 0),getLongAddress(getVaildOPcode(lstASMLines, index, 0)) + lstAnyCommand))
                            intAny += 1
                        lstASMLines] = "" #the third paramter must be 0 (del the first line everytime)
                  if lstAnyToWrite == []:
                        lstASMLines = lstTempToWrite
                  else:
                        for windex, strTowrite in lstAnyToWrite:
                            lstASMLines = strTowrite
                            debugOut("-->any write(%s), %s"%(windex, strTowrite))
    return lstASMLines


def WriteOutFile(strPath, lstASMLines):
    fw = open(strPath, 'w')
    for line in lstASMLines:
      if line != "":
            fw.write(line.strip("\n") + "\n")
    fw.close()
   
#note:idata > 0 ok <0 ok
#note:any : any command


lines = open("input3.txt").readlines()
ans = lines
for i in range(0,6):
    print(i)
    ans = ScanAndDel(['call','add dword ptr ss:','retn'], lines, 'NONE')
    ans = ScanAndDel(['call','sub dword ptr ss:','retn'], ans, 'NONE')
    ans = ScanAndDel(['NOP'], ans, 'NONE')
    ans = ScanAndDel(['call','add esp,0x4'], ans, 'NONE')
    ans = ScanAndDel(['mov dword ptr ss:,reg','lea esp,dword ptr ss:','lea esp,dword ptr ss:','mov reg,dword ptr ss:'], ans, [])
    ans = ScanAndDel(['mov dword ptr ss:,reg','sub esp,0x4','pop reg'], ans, [])
    ans = ScanAndDel(['call','lea esp,dword ptr ss:'], ans, 'NONE')
    ans = ScanAndDel(['sub ebp,ebp','or ebp,esp'], ans, 'NONE', 'mov ebp,esp')
    ans = ScanAndDel(['lea esp,dword ptr ss:'], ans, 'NONE','mov esp,ebp')
    ans = ScanAndDel_MulReg(['push reg1','mov reg1,reg2','and reg1,reg3','mov reg2,','xchg reg1,reg2','pop reg1'], ans, 3, ['eax','ebx','ecx','edx'], 'and reg2,reg3')
    ans = ScanAndDel_MulReg(['push reg1','mov reg1,idata','xchg reg1,reg2','pop reg1'], ans, 2, ['eax', 'ebx', 'ecx', 'edx'], 'mov reg2,idata')
    ans = ScanAndDel_MulReg(['push reg1','xchg reg2,reg1','mov reg2,idata','sub reg1,reg2','mov reg2,reg1','pop reg1'], ans, 2, ['eax', 'ebx', 'ecx', 'edx'], 'sub reg1,idata')
    ans = ScanAndDel_MulReg(['xor reg1,reg1','or reg1,idata'], ans, 1, lst_AllREGS, 'mov reg1,idata')
    ans = ScanAndDel_MulReg(['sub reg1,reg1','or reg1,idata'], ans, 1, lst_AllREGS, 'mov reg1,idata')
    ans = ScanAndDel_MulReg(['lea reg1,dword ptr ds:'], ans, 1, lst_AllREGS, 'add reg1,idata')
    ans = ScanAndDel_MulReg(['lea reg1,dword ptr ds:, ans, 1, lst_AllREGS, 'add reg1,idata')
    ans = ScanAndDel_MulReg(['push reg1','mov reg1,idata','xchg reg1,reg2','pop reg1'], ans, 2, lst_AllREGS, 'mov reg2,idata')
    ans = ScanAndDel_MulReg(['not reg1','not reg1'], ans, 1, lst_AllREGS, "")
    ans = ScanAndDel_MulReg(['mov reg1,reg2','and reg1,reg2'], ans, 2, lst_AllREGS, 'mov reg1,reg2')
    ans = ScanAndDel_MulReg(['push reg1','mov reg1,reg2','mov reg2,','xchg reg1,reg2','pop reg1'], ans, 2, lst_AllREGS, "")
    ans = ScanAndDel_MulReg(['push reg1','mov reg1,reg2','and reg1,reg3','mov reg2,reg1','pop reg1'], ans, 3, lst_AllREGS,"and reg2,reg3")
    ans = ScanAndDel_MulReg(['push reg1','mov reg2,','pop reg2'], ans, 2, lst_AllREGS, "mov reg2,reg1")
    ans = ScanAndDel_MulReg(['push reg1','mov reg1,','pop reg1'], ans, 1, lst_AllREGS, '')
    ans = ScanAndDel_MulReg(['push reg1','xchg reg1,','pop reg1'], ans, 1, lst_AllREGS, '')
    ans = ScanAndDel_MulReg(['mov reg1,reg1'], ans, 1, lst_AllREGS, '')
    ans = ScanAndDel_MulReg(['and reg1,reg1'], ans, 1, lst_AllREGS, '')
    ans = ScanAndDel_MulReg(['lea reg1,dword ptr ds:'], ans, 2, lst_AllREGS, 'mov reg1,reg2')
    ans = ScanAndDel_MulReg(['mov reg1,reg2','mov reg2,reg1'], ans, 2, lst_AllREGS, 'mov reg1,reg2')

    ans = ScanAndDel_MulReg(['push reg1','mov reg1,reg2','and reg1,reg3','mov reg2,reg1','pop reg1'],ans, 3, lst_AllREGS, 'and reg2,reg3')
    ans = ScanAndDel_MulReg(['push reg1','mov reg1,reg2','xchg reg2,reg1','pop reg1'], ans, 2, lst_AllREGS, "")
    ans = ScanAndDel_MulReg(['push reg1','mov reg1,reg2','and reg1,reg3','mov reg2,','xchg reg2,reg1','pop reg1'], ans, 3, lst_AllREGS, "and reg2,reg3")
    ans = ScanAndDel_MulReg(['not reg1','mov reg2,idata','not reg1'],ans,2,lst_AllREGS,'mov reg2,idata')
    #ans = ScanAndDel_MulReg(['push reg1','mov reg1,reg2','any','any','any','xchg reg1,reg2','pop reg1'],ans,2,lst_AllREGS,"")
    #ans = ScanAndDel_MulReg(['push reg1','mov reg1,reg2','mov reg2','any','xchg reg2,reg1','pop reg1'],ans,2,lst_AllREGS,"")
    ans = ScanAndDel_MulReg(['push reg1','mov reg1,reg2','add reg2,','xchg reg1,reg2','pop reg1'],ans,2,lst_AllREGS,"")
WriteOutFile("output.txt", ans)

moranyuyan 发表于 2020-7-7 07:38

谢谢分享

dzc999 发表于 2020-7-7 07:48


感谢分享

gh0st_ 发表于 2020-7-7 23:15

感谢分享

monicappp 发表于 2020-7-8 10:49

感谢分享教程

zhoumeto 发表于 2020-7-8 10:50

学习学习

gblw 发表于 2020-7-8 12:23

感谢分享

fengbolee 发表于 2020-7-8 17:59

感谢技术分享,评分双手送上。

cici300 发表于 2020-7-9 09:20

学习 谢谢

langyatudou 发表于 2020-7-14 17:25

感谢分享
页: [1] 2
查看完整版本: (抛砖引玉)x86反-乱序/膨胀处理脚本