目录

1:纪念一下第一个自己独立做出来re题(虽然很简单):

2:攻防世界新手区no-strings-attached复现: 

3:攻防世界simple-check-100复现:

1:纪念一下第一个自己独立做出来re题(虽然很简单):

open-source复现:

给出一段c源码:

#include <stdio.h>#include <string.h>int main(int argc, char *argv[]) {if (argc != 4) {printf("what?\n");exit(1);}unsigned int first = atoi(argv[1]);if (first != 0xcafe) {printf("you are wrong, sorry.\n");exit(2);}unsigned int second = atoi(argv[2]);if (second % 5 == 3 || second % 17 != 8) {printf("ha, you won't get it!\n");exit(3);}if (strcmp("h4cky0u", argv[3])) {printf("so close, dude!\n");exit(4);}printf("Brr wrrr grr\n");unsigned int hash = first * 31337 + (second % 17) * 11 + strlen(argv[3]) - 1615810207;printf("Get your key: ");printf("%x\n", hash);return 0;}

分析:方法1:

攻防世界(动态调试题)-编程知识网

C 库函数 int atoi(const char *str) 把参数 str 所指向的字符串转换为一个整数(类型为 int 型)。

First=0xcafe=51966D

攻防世界(动态调试题)-编程知识网

Second%17=8

攻防世界(动态调试题)-编程知识网

argv[3]= "h4cky0u"

攻防世界(动态调试题)-编程知识网

攻防世界(动态调试题)-编程知识网

攻防世界(动态调试题)-编程知识网

方法2,发现有些人是把c++源码编译成exe文件直接运行生成flag的,学习了如何生成exe文件的方法:

攻防世界(动态调试题)-编程知识网

攻防世界(动态调试题)-编程知识网

但会发现,把这个exe文件放在别的电脑上不一定能执行,因为缺少运行环境,以vc++2010所需要的运行时环境为例,发现生成的exe文件闪退的话,开头加上#include <stdlib.h>;在main函数的末尾加上 system("pause");  如果有 return ;,那么加在 return ; 的前面。

总结:

1:学习了怎么通过c++生成exe文件

2:学习了生成的exe文件闪退的解决方法

3:关于c++的一些基础语法可以了解一下

学习了ida的断点调试、idapy脚本、Linux下gdb动态调试的使用:

2:攻防世界新手区no-strings-attached复现: 

方法1:脚本求解:

查壳,发现是Linux elf 格式的可执行文件,于是去虚拟机运行,并没有发现什么有价值的东西,并且出错了

攻防世界(动态调试题)-编程知识网

Main函数,逐一分析main函数里的函数,发现authenticate()函数中有字符串比较:

攻防世界(动态调试题)-编程知识网

跟进authenticate()函数: 

攻防世界(动态调试题)-编程知识网

意思是&s, &dword_8048A90中的值解密赋给s2,键盘输入赋给ws,s2和ws进行比较是否相等,可得s2就是要找的flag,其中有一些看不懂的函数:

  1. fgetws/fgets(ws,n,stdin) 函数中的 stdin 表示标准输入,如键盘输入。函数作用是判断ws输入值是否为空
  2. wcslen()函数:返回字符串的长度,\0之前的字符长度

跟进decrypt函数,s2是怎么加密的:

攻防世界(动态调试题)-编程知识网

malloc()函数向系统申请分配size字节的内存空间。

dest存储了s的值,用s的每一个字符和a2相减得到新值,注意这里有两个循环,a2的字符数比s少,所以a2可以多次循环直到s的字符串减完。

找到&s, &dword_8048A90中的值,这里可以用idapy脚本分别提取ascii码值(File->script command),发现并没有什么用,于是shift+e导出10进制值:

攻防世界(动态调试题)-编程知识网

攻防世界(动态调试题)-编程知识网

导出10进制:

攻防世界(动态调试题)-编程知识网

两个参数的类型都是 wchar_t 类型(长度 16 位或 32 位,即2字节或4 字节),显然这里是32位即4字节的变量,4字节为一个整体,所以删除后面 4 个字节的 0,也可以不删。

写脚本:

攻防世界(动态调试题)-编程知识网

方法2:ida下断点动调:

准备工作,因为是Linux下的elf文件,所以ida动调要连接远程Linux虚拟机:

攻防世界(动态调试题)-编程知识网

提取s2的值:

攻防世界(动态调试题)-编程知识网

F9运行,出现提示框:

攻防世界(动态调试题)-编程知识网

攻防世界(动态调试题)-编程知识网

点ok后进入ida动态调试:

攻防世界(动态调试题)-编程知识网

双击eax:

攻防世界(动态调试题)-编程知识网

Idapython运行一下,提取字符(File->script command):

攻防世界(动态调试题)-编程知识网

方法3:Gdb动调(gdb是基于Linux下的,因为本题的文件是Linux的elf文件):

攻防世界(动态调试题)-编程知识网

找到该函数下的汇编语句(text view跳转),发现decrypt函数返回的值存在0x8048725地址处的eax处:

攻防世界(动态调试题)-编程知识网

用gdb动态调试:

攻防世界(动态调试题)-编程知识网

gdb 123 -q——启动gdb并导入文件:

攻防世界(动态调试题)-编程知识网

在decrypt函数处下断点:

攻防世界(动态调试题)-编程知识网

r运行至decrypt断点处,此处的地址是0x804865c:

攻防世界(动态调试题)-编程知识网

n单步步过,执行0x804865c处decrypt函数的命令:

攻防世界(动态调试题)-编程知识网

i r查看此时寄存器值

攻防世界(动态调试题)-编程知识网

x/6sw $eax,显示eax寄存器中前6行数据

6:显示6行数据

s:字符串形式

w:word(4字节)形式

攻防世界(动态调试题)-编程知识网

发现不能用OD动调,因为OD只能调试32位的pe文件,而该文件是elf文件,现在发现除了OD,可以进行动调的还有Linux下的gdbida

进阶:

3:攻防世界simple-check-100复现:

解压出来3个文件:

攻防世界(动态调试题)-编程知识网

main函数:

攻防世界(动态调试题)-编程知识网

攻防世界(动态调试题)-编程知识网

攻防世界(动态调试题)-编程知识网

这道题有些意思,发现check_key函数里输入的值v39只和if条件为真有关,和interesting_function函数最后输出的flag值无关,所以想直接interesting_function函数写脚本求解,但是发现a1是一个十进制数,v6=a1,也就是v3值是a1各内存单元里的值,但是不知道怎么提取,所以就不知道静态怎么做,试试动态调试。

动态调试的话,可以用ida调试exe文件,修改eax值,使check函数为真

Ida调试exe文件

准备:

攻防世界(动态调试题)-编程知识网

攻防世界(动态调试题)-编程知识网

Ida准备:

攻防世界(动态调试题)-编程知识网

攻防世界(动态调试题)-编程知识网

Hostname选择127.0.0.1,最后点F9运行进入调试界面

在004015A4、004015B3处下断点,命令行key:输入任意值,回车运行至第一个断点处,修改eax返回值,使if条件为真,F9运行至第二个断点处。同时输出flag

攻防世界(动态调试题)-编程知识网

F9继续运行

攻防世界(动态调试题)-编程知识网

发现是乱码,不是正确的flag,于是使用压缩包里的elf文件。

除更改eax返回值外,还可以阻止jz跳转(把jz改成nop或其他无关指令,下断点运行)

攻防世界(动态调试题)-编程知识网

 将004015A6处的指令修改为任意指令,F9

攻防世界(动态调试题)-编程知识网 

攻防世界(动态调试题)-编程知识网

修改汇编指令:

方法一:

攻防世界(动态调试题)-编程知识网

方法二:

攻防世界(动态调试题)-编程知识网

F2保存

攻防世界(动态调试题)-编程知识网

也可以用OD调试exe文件。

ctrl+g跳转至004015A4处,下断点F9,je跳转命令用nop填充,F8单步步过至调用完interesting_function函数(call 00401432),输出flag,当然也通过可以更改eax返回值为1的发生输出flag

攻防世界(动态调试题)-编程知识网

攻防世界(动态调试题)-编程知识网

攻防世界(动态调试题)-编程知识网

发现给的压缩包里除了exe还有elf文件,也试试Linux下的gdb动态调试。

介绍gdb:gdb(GNU Debugger),可用于在开发程序时检查正在运行的进程并解决问题。设置断点是学习使用 GNU 调试器的第一步。程序在达到断点时停止,可以运行 gdb 的命令对其进行检查或更改变量,然后再允许该程序继续运行。

简而言之,gdb是Linux下的调试器,可以调试elf文件,类似于windows下的OD。

思路:改变check_key函数的返回值(set $eax=1),使函数条件为真,c继续运行输出flag 

gdb

File XXX    是导入XXX文件的意思——相当于gdb XXX -q

gdb 111 -q  启动gdb并导入文件111

b main      在main函数处下断点,也可以直接b *0x4008dd

r            运行

现在运行至0x4007c0地址处

攻防世界(动态调试题)-编程知识网

 n         单步运行直到运行至0x4008E2处,此时已调用了check_key函数,产生 eax返回值,为使if条件为真,把eax返回值修改为1

set $eax=1

i r eax 查看eax的值)

攻防世界(动态调试题)-编程知识网

攻防世界(动态调试题)-编程知识网

c         继续运行,输出flag

攻防世界(动态调试题)-编程知识网

总结:

1:ida中text view汇编语句的理解,注意和伪代码对应

2:eax里保存函数返回值

3:gdb调试器的命令使用

4:test命令:

含义:test AX,BX 与add AX,BX命令有相同效果,只是test指令不改变AX和BX的内容,而add指令会把结果保存到AX中。

用法:用来测试一方寄存器是否为空,如果eax相加的临时值为零,设置ZF零标志为1,jz跳转至else,所以该题要不使 jz执行,就要让eax不为0,可以设置为1,这是把eax返回值修改为1的汇编层面解释。

攻防世界(动态调试题)-编程知识网

Ps:jnz跳转的条件和jz相反,jnz是text相加的临时值为1, ZF=0

Ps:peda一款实用的GDB插件增强gdb的显示:在调试过程中着色并显示反汇编代码,寄存器和内存信息。可以学习怎么安装peda。

Ps:elf文件和pe文件:

PE是windows引入的一种可执行文件格式,该格式和Linux系统的ELF文件格式同源,都是由COFF格式发展而来。