update pin

This commit is contained in:
firmianay 2017-08-08 23:25:51 +08:00
parent 5721728369
commit c7f996ee95
6 changed files with 123 additions and 6 deletions

View File

@ -113,7 +113,7 @@ sci:
## Pin 简介
Pin 是 Intel 公司研发的一个动态二进制插桩框架,可以在二进制程序运行过程中插入各种函数,以监控程序每一步的执行。
Pin 是 Intel 公司研发的一个动态二进制插桩框架,可以在二进制程序运行过程中插入各种函数,以监控程序每一步的执行。[官网](https://software.intel.com/en-us/articles/pin-a-dynamic-binary-instrumentation-tool)(目前有 2.x 和 3.x 两个版本2.x 不能在 Linux 内核 4.x 及以上版本上运行,这里我们选择 3.x
Pin 具有一下优点:
- 易用
@ -161,27 +161,27 @@ $ cd source/tools/MyPintools
```
对于 32 位架构,使用 `TARGET=ia32`
```
$ make obj-ia32/mypintool.so TARGET=ia32
[MyPintools]$ make obj-ia32/mypintool.so TARGET=ia32
```
对于 64 位架构,使用 `TARGET=intel64`
```
$ make obj-intel64/mypintool.so TARGET=intel64
[MyPintools]$ make obj-intel64/mypintool.so TARGET=intel64
```
启动并插桩一个应用程序:
```
$ ../../../pin -t obj-intel64/mypintools.so -- application
[MyPintools]$ ../../../pin -t obj-intel64/mypintools.so -- application
```
其中 `pin` 是插桩引擎,由 Pin 的开发者提供;`pintool.so` 是插桩工具,由用户自己编写并编译。
绑定并插桩一个正在运行的程序:
```
$ ../../../pin -t obj-intel64/mypintools.so -pid 1234
[MyPintools]$ ../../../pin -t obj-intel64/mypintools.so -pid 1234
```
## Pintool 示例分析
Pin 提供了一些 Pintool 的示例,下面我们分析一下用户手册中介绍的指令计数工具 inscount。
Pin 提供了一些 Pintool 的示例,下面我们分析一下用户手册中介绍的指令计数工具,可以在 `source/tools/ManualExamples/inscount0.cpp` 中找到
```c
#include <iostream>
#include <fstream>
@ -259,6 +259,15 @@ int main(int argc, char * argv[])
- 在每条指令之前(`IPOINT_BEFORE`)执行分析函数 `docount()`,功能是对全局变量递增计数。
- 执行完成函数 `Fini()`,输出计数结果到文件。
由于我当前使用的系统和内核版本过新Pin 暂时还未支持,使用时需要加上 `-ifeellucky` 参数,`-o` 参数将运行结果输出到文件。运行程序:
```
[ManualExamples]$ uname -a
Linux manjaro 4.11.5-1-ARCH #1 SMP PREEMPT Wed Jun 14 16:19:27 CEST 2017 x86_64 GNU/Linux
[ManualExamples]$ ../../../pin -ifeellucky -t obj-intel64/inscount0.so -o inscount0.log -- /bin/ls
[ManualExamples]$ cat inscount0.log
Count 528090
```
## Pintool 编写
#### main 函数的编写
@ -323,3 +332,93 @@ Pintool 的入口为 `main` 函数,通常需要完成下面的功能:
## Pin 在 CTF 中的应用
由于程序具有循环、分支等结构,每次运行时执行的指令数量不一定相同,于是我们可是使用 Pin 来统计执行指令的数量,从而对程序进行分析。特别是对一些使用特殊指令集和虚拟机,或者运用了反调试等技术的程序来说,相对于静态分析去死磕,动态插桩技术是一个比较好的选择。
我们先举一个例子,[源码](../source/Others/5.2_pin.c)如下:
```c
#include<stdio.h>
#include<string.h>
void main() {
char pwd[] = "abc123";
char str[128];
int flag = 1;
scanf("%s", str);
for (int i=0; i<=strlen(pwd); i++) {
if (pwd[i]!=str[i] || str[i]=='\0'&&pwd[i]!='\0' || str[i]!='\0'&&pwd[i]=='\0') {
flag = 0;
}
}
if (flag==0) {
printf("Bad!\n");
} else {
printf("Good!\n");
}
}
```
这段代码要求用户输入密码,然后逐字符进行判断。
使用前面分析的指令计数的 inscount0 Pintool我们先测试下密码的长度
```
[ManualExamples]$ echo x | ../../../pin -ifeellucky -t obj-intel64/inscount0.so -o inscount.out -- ~/a.out ; cat inscount.out
Bad!
Count 152667
[ManualExamples]$ echo xx | ../../../pin -ifeellucky -t obj-intel64/inscount0.so -o inscount.out -- ~/a.out ; cat inscount.out
Bad!
Count 152688
[ManualExamples]$ echo xxx | ../../../pin -ifeellucky -t obj-intel64/inscount0.so -o inscount.out -- ~/a.out ; cat inscount.out
Bad!
Count 152709
[ManualExamples]$ echo xxxx | ../../../pin -ifeellucky -t obj-intel64/inscount0.so -o inscount.out -- ~/a.out ; cat inscount.out
Bad!
Count 152730
[ManualExamples]$ echo xxxxx | ../../../pin -ifeellucky -t obj-intel64/inscount0.so -o inscount.out -- ~/a.out ; cat inscount.out
Bad!
Count 152751
[ManualExamples]$ echo xxxxxx | ../../../pin -ifeellucky -t obj-intel64/inscount0.so -o inscount.out -- ~/a.out ; cat inscount.out
Bad!
Count 152772
[ManualExamples]$ echo xxxxxxx | ../../../pin -ifeellucky -t obj-intel64/inscount0.so -o inscount.out -- ~/a.out ; cat inscount.out
Bad!
Count 152779
```
我们输入的密码位数从 1 到 7可以看到输入位数为 6 位或更少时,计数值之差都是 21而输入 7 位密码时,差值仅为 7不等于 21。于是我们知道程序密码为 6 位。接下来我们更改密码的第一位:
```
[ManualExamples]$ echo axxxxx | ../../../pin -ifeellucky -t obj-intel64/inscount0.so -o inscount.out -- ~/a.out ; cat inscount.out
Bad!
Count 152786
[ManualExamples]$ echo bxxxxx | ../../../pin -ifeellucky -t obj-intel64/inscount0.so -o inscount.out -- ~/a.out ; cat inscount.out
Bad!
Count 152772
[ManualExamples]$ echo cxxxxx | ../../../pin -ifeellucky -t obj-intel64/inscount0.so -o inscount.out -- ~/a.out ; cat inscount.out
Bad!
Count 152772
[ManualExamples]$ echo dxxxxx | ../../../pin -ifeellucky -t obj-intel64/inscount0.so -o inscount.out -- ~/a.out ; cat inscount.out
Bad!
Count 152772
```
很明显,程序密码第一位是 `a`,接着尝试第二位:
```
[ManualExamples]$ echo aaxxxx | ../../../pin -ifeellucky -t obj-intel64/inscount0.so -o inscount.out -- ~/a.out ; cat inscount.out
Bad!
Count 152786
[ManualExamples]$ echo abxxxx | ../../../pin -ifeellucky -t obj-intel64/inscount0.so -o inscount.out -- ~/a.out ; cat inscount.out
Bad!
Count 152800
[ManualExamples]$ echo acxxxx | ../../../pin -ifeellucky -t obj-intel64/inscount0.so -o inscount.out -- ~/a.out ; cat inscount.out
Bad!
Count 152786
[ManualExamples]$ echo adxxxx | ../../../pin -ifeellucky -t obj-intel64/inscount0.so -o inscount.out -- ~/a.out ; cat inscount.out
Bad!
Count 152786
```
第二位是 `b`,同时我们还可以发现,每一位正确与错误的指令计数之差均为 14。同理我们就可以暴力破解出密码但这种暴力破解方式大大减少了次数提高了效率。破解脚本可查看参考资料。
#### 参考资料
[A binary analysis, count me if you can](http://shell-storm.org/blog/A-binary-analysis-count-me-if-you-can/)
[pintool2](https://github.com/sebastiendamaye/pintool2)
#### 练习
[Baleful - picoCTF 2014](../src/5.2_baleful)
[Reverse 400 - Hack You 2014](../src/Reverse/5.2_reverse_400)
[wyvern 500 - CSAW CTF 2015](../src/Reverse/5.2_wyvern_500)
[rev100 - th3jackers CTF 2015](../src/5.2_th3jackers_100)

18
src/Others/5.2_pin.c Normal file
View File

@ -0,0 +1,18 @@
#include<stdio.h>
#include<string.h>
void main() {
char pwd[] = "abc123";
char str[128];
int flag = 1;
scanf("%s", str);
for (int i=0; i<=strlen(pwd); i++) {
if (pwd[i]!=str[i] || str[i]=='\0'&&pwd[i]!='\0' || str[i]!='\0'&&pwd[i]=='\0') {
flag = 0;
}
}
if (flag==0) {
printf("Bad!\n");
} else {
printf("Good!\n");
}
}

BIN
src/Reverse/5.2_baleful Executable file

Binary file not shown.

BIN
src/Reverse/5.2_reverse_400 Executable file

Binary file not shown.

BIN
src/Reverse/5.2_th3jackers_100 Executable file

Binary file not shown.

BIN
src/Reverse/5.2_wyvern_500 Executable file

Binary file not shown.