在逆向学习里面遇到的一些比较方便的算法啥的,就总结在这里,虽然杂但是应该会有用<( ̄▽ ̄)/

IDA-IDC

(自从idapython能用之后,我打算放弃idc了,所以idc到这里就没了,idc确实没有python方便,我认了,来自某高的建议(手动狗头))
定义:
auto i,j,k;
extern outsideGlobal; //引入全局变量声明

常用函数

void PatchByte(long addr , long val) 设置虚拟地址addr处的一个字节值,PatchByte可更换为
PatchWord,PatchDword设置虚拟地址addr处的2字节和4字节值。

long Byte(long addr) 从虚拟地址addr读取一个字节值,Byte可更换为Word,Dword读取2字节和4字节值。

void Message(string format , …),在输出窗口打印一条格式化消息。

void print(…),在输出窗口中打印每个参数的字符串表示形式。

long atol(string val),将10进制val转化成对应整数值。

long xtol(string val),将16进制val转化成对应整数值。

long ord(string ch),返回单字符字符串ch的ASCII值。

string Name(long addr),返回与给定地址有关的名称,如果该位置没有名称,则返回空字符串。

string用法

和python一样

auto str = “String to slice”;
auto s1, s2, s3, s4;
s1 = str[7:9];          //'to'
s2 = str[ :6];           //'String'
s3 = str[10: ];           //'slice'
s4 = str[5];               //'g'

上述内容摘抄于Thunder_J的csdn

注意问题

里面的语法不支持i+=1;只支持i=i+1
想打印出ascii值,需要的是Message(“%x”,ord(xxx)),必须要有前面的格式化字符,不然只会给你打印出字符来。

ctf实践

auto i;
for(i=0x40213b;i>=0x402124;i--)
{
    Message((Byte(i)^6)-1);        //我发现他自己转成字符串了,真方便O(∩_∩)O~~
}
Message("\n")

idc功能实现

IDA-Python

不管怎么样,python牛逼

ea代表地址
一些常规操作,暂时还没咋用到

①here()==ScreenEA() #打印当前光标标记地址
②GetDisasm(ea) #打印地址处汇编指令
③GetMnem(ea) #只打印指令例如mov cmp之类
④GetOpnd(ea,n) #操作数,rax,rdx之类,n有0,1,分别表这句汇编指令的某个操作数
⑥SegName(ea) SegStart(ea) SegEnd(ea) #段名称、段初始地址、段结束地址
⑦for fuc in Functions():
   print hex(fuc),GetFunctionName(fuc) //遍历函数

**显示地址处的字节数**
Byte()         #同理还有word(ea)、Dword(ea)、Qword(ea)、GetFloat(ea)、GetDouble(ea)
**patch数据**
PatchByte(ea, value)、PatchWord(ea, value)、PatchDword(ea, value)

这里展现一下效果图
python功能实现

实际运用

这里先放一个恶意代码里面说的修改call颜色,等以后再放自己实践用到的
from idautils import
from idc import

heads = Heads(SegStart(ScreenEA()),SegEnd(ScreenEA()))
fuc=[]
for i in heads:
    if GetMnem(i) == "call":
        fuc.append(i)
print(len(fuc))
for i in fuc:
    SetColor(i,CIC_ITEM,0xc7fdff)

call改色

C语言

常见函数

atoi && _itoa

atoi

参数:char

作用:字符串(字符串为char类型)转int型

a="123";
b=atoi(a);
printf(b);

输出:123(且int b=123)

atoi有一个特性,遇到非数字就会截止转换,但前面的会转换

_itoa(value,string,radix)

参数
value:欲转换的数据。
string:目标字符串的地址。
radix:转换后的进制数,可以是10进制、16进制等,范围必须在 2-36。

作用:int型转字符串

做了一道功放世界新放的逆向,名称:Mysterious
难度不大,想试着直接静态调试,发现卡在了一个函数身上,思路也是卡死了,应该想到这是一道溢出的
ida图片分析如下
Mysterious
思路想通了很简单,溢出string给到v12、v13、v14,然后string给v10,就是卡在了atoi遇到非数字就截止但前面都会转换的功能上,知道之后,输入122xyz,122给了v10,剩下xyz分别给了v12、v13、v14,得到结果
Mysterious

本内容中的参数摘抄于lanzhihui_的csdn

C格式问题

1.for循环,想要4个4个的跳,第三部分格式应为i=i+4而不是i+=4,不然会报Missing brace

python

pyton的一些骚姿势(就是简便代码写法)

for循环可以写成 [print(i) for i in range(10)] (后面的很多式子都会用到这个)

字符和数组[asc码]的拼接 str+="".join([chr(i) for i in (arr)])

a1,a2的快速建立(z3用的比较方便):[print("a%d=%d" % (i,arr[i])) for i in range(10)](将arr值分别给a1,a2,a3)

字典的建立

个人感觉没啥用,但也算是知识点,就放到这里来

a=[1,2,3];b=['a','b','c']
ddd=zip(a,b)        #zip()将a,b打包成元祖,就是1和a一组,2和b一组
dic=dict(ddd)        #建立dict字典    dict正常建立:dict={1:'a',2:'b'}    
print(dic)    

效果图如下
python字典
这里说一下,我在做ctf移位复原器的时候,想用这个,但发现如果里面dic[]里面的值是一种式子而不是直接的指定字符,就类似与是dic[mov_dic[i+2]]而不是dic[1]返回的类型就会一直是nobetype,什么也没法转换的一种类型,我人都傻了,技能有限,等以后有这个实力了,再继续利用

re正则表达式的应用

这种库就是类似于搜索关键字,或者是把一种写作形式换成另一种写作形式,自动化的文本替换,学习一下,在z3里面用的比较多,可以格式化很多东西,到时候二进制文件内部编辑应该会方便许多,先学会

###函数介绍:
re.match(pattern,string,flags) #pattern:表达式、string:目标字符串
只与string开头进行匹配,开头没有返回none,有的话返回相应的group字符串

re.search(pattern,string,flags)
从整个string进行匹配,返回同理match

re.sub(pattern,repl,string,count,flags) #count:替换最大次数,默认0全替换
从string匹配pattern然后替换成repl

re.compile(pattern,flag)
产生一种pattern,用来直接送给match、search用

re.findall(string, pos, endpos) #pos字符串起始位置 endpos结束位置
把所有匹配都找出来,match、search只找一次,用数组的形式传出来,只能和compile合作使用

re.finditer(pattern,string,flags)
迭代方式把所有匹配表示出来,只能通过for i in it的方式表达,it的类型是callable-iterator,数组引不出来

###实例:

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import re
s1="I"
s2="I Love you baby"
s3='baby'

#match、search匹配
match1=re.match(s1,s2)                            
print(match1.group())                                
search1=re.search(s3,s2)
print(search1.span(),search2.span())

#group展示(这里(.*)算一个group,.*只进行匹配不放进group)
seobj=re.search(r'(.*) (.*?) you .*',s2)
print(seobj.group())
print(seobj.group(1))
print(seobj.group(2))

#sub应用
phone = "2004-959-559 # 这是一个国外电话号码" 
# 删除字符串中的 Python注释 
num = re.sub(r'#.*', "", phone)
print "电话号码是: ", num
print phone
# 删除非数字(-)的字符串 
num = re.sub(r'\D', "", phone)        #(\D将除数字外的东西全部去掉)
print "电话号码是 : ", num

#compile、findall、finditer应用
patt=re.compile(r'\d+')
m = patt.search("abxs12s45sads74")
print m.group()
print m.start()
print m.end()
print m.span()
m = patt.findall("abxs12s45sads74")
print m
it = re.finditer(r"\d+","12a32bc43jf3") 
for i in it: 
    print (i.group() )

效果图:
re效果图

###flag库和表达式类型

#flag库
    re.I 忽略大小写
    re.L 表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境
    re.M 多行模式
    re.S 即为 . 并且包括换行符在内的任意字符(. 不包括换行符)
    re.U 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性数据库
    re.X 为了增加可读性,忽略空格和 # 后面的注释

表达式类型:
表达是类型图1
表达是类型图2
表达是类型图3

##

pe\elf相关文件处理

PE修改OEP

这个操作很简单,修改一个值就ok了,可以PE-tools,可以直接二进制编译器,都可,亲测有效

首先自己写了一个c语言脚本做判断,编译出来发现是jump起步,因为用的vs,不过这都无所谓了。我们发现这堆jmp下面就有一堆空代码所以直接利用
od图

空位置写入jmp的机器码,卡了一会,明白了原理,E9是jmp后面四个字节(dword)用来放偏移,上偏就是负数,下偏就是正数,base值是这块指令地址+5,然后根据计算,我们要去0x343,在0x398+5进行改变,既0x39d,然后0x343-0x39d=0xffffffa6,写上去就行,上图末端有展示

然后PE-tools修改oep
pe-tools
二进制工具修改oep
二进制工具

最终结果oep都发生了改变
结果图


一个好奇的人