题目:


IDA反编译

主函数

 1 int __cdecl main(int argc, const char **argv, const char **envp)
2 {
3 char s2[144]; // [rsp+0h] [rbp-1A0h] BYREF
4 char s1[128]; // [rsp+90h] [rbp-110h] BYREF
5 char input[136]; // [rsp+110h] [rbp-90h] BYREF
6 int key; // [rsp+198h] [rbp-8h]
7 int input_len; // [rsp+19Ch] [rbp-4h]
8
9 memset(input, 0, 0x80uLL);
10 memset(s1, 0, sizeof(s1));
11 memset(s2, 0, sizeof(s2));
12 s2[0] = 0x9C;
13 s2[1] = 0xCC;
14 s2[2] = 0x88;
15 s2[3] = 0x76;
16 s2[4] = 0xD7;
17 s2[5] = 0x89;
18 s2[6] = 0x78;
19 s2[7] = 0xEC;
20 s2[8] = 0x7C;
21 s2[9] = 0xD7;
22 s2[10] = 0x89;
23 s2[11] = 0x71;
24 s2[12] = 0xE3;
25 s2[13] = 0x6D;
26 s2[14] = 0x98;
27 s2[15] = 0x17;
28 s2[16] = 0x94;
29 s2[17] = 0xF;
30 s2[18] = 0xCA;
31 s2[19] = 0x9F;
32 s2[20] = 0x7E;
33 s2[21] = 0xD9;
34 s2[22] = 0xA0;
35 s2[23] = 0x8A;
36 s2[24] = 0x79;
37 s2[25] = 0xD1;
38 s2[26] = 0x80;
39 s2[27] = 0x77;
40 printf(&byte_400A66, s2, 18LL);
41 fgets(input, 128, stdin);
42 input_len = strlen(input);
43 if ( input[input_len - 1] == 10 )
44 input[input_len - 1] = 0;
45 key = generate_key(877);
46 encrypt((__int64)input, (__int64)s1, 2024, key);
47 if ( !memcmp(s1, s2, 128uLL) )
48 puts("success");
49 else
50 puts("fail");
51 return 0;
52 }

加密函数

 1 __int64 __fastcall encrypt(__int64 input, __int64 s1, int num2024, int key)
2 {
3 __int64 result; // rax
4 int i; // [rsp+20h] [rbp-8h]
5 int v6; // [rsp+24h] [rbp-4h]
6 unsigned int v7; // [rsp+24h] [rbp-4h]
7
8 v6 = 0;
9 for ( i = 0; i <= 127; ++i )
10 {
11 result = *(unsigned __int8 *)(i + input); // input[i]=result
12 if ( (_BYTE)result )
13 {
14 v7 = key + num2024 + v6;
15 *(_BYTE *)(i + s1) = *(_BYTE *)(i + input) + v7;// s1[i]=input[i]+v7
16 // v7是偏移量
17 result = (v7 >> 4) ^ *(unsigned __int8 *)(i + s1);// 等于没有
18 v6 = (v7 >> 4) ^ *(unsigned __int8 *)(i + s1);// v6储存的是上一个result的值
19 }
20 }
21 return result;
22 }

KEY

1 __int64 __fastcall generate_key(int a1)
2 {
3 return (unsigned int)(1540483477 * a1 + 305419896) >> 16;
4 }

输入值

s2 = [
0x9C, 0xCC, 0x88, 0x76, 0xD7, 0x89, 0x78, 0xEC,
0x7C, 0xD7, 0x89, 0x71, 0xE3, 0x6D, 0x98, 0x17,
0x94, 0x0F, 0xCA, 0x9F, 0x7E, 0xD9, 0xA0, 0x8A,
0x79, 0xD1, 0x80, 0x77
]

个人记录

获得key值——C代码

参考大佬的部分wp:2024ctfshow元旦水友赛 RE re_signin-CSDN博客

 1 #include<stdio.h>
2
3 unsigned int ge(unsigned int s) {
4 s = 1540483477 * s + 305419896;
5 return (s >> 16);
6 }
7
8 int main() {
9 unsigned int k = 877; // 为变量 k 赋一个初始值
10 unsigned int key = ge(k); // 调用 ge 函数来计算密钥 key
11 printf("%x", key); // 使用 %x 格式化字符串打印无符号整数值(十六进制)
12 return 0;
13 }

最初的代码11行用的是"%u"——打印出来的是十进制数:41041

但是参考了大佬的py代码:ctfshow 元旦水友赛部分wp | M4sh1r0の万事屋 (m4shir0.com)

大佬用的是十六进制,写解题脚本的时候也是多用0xA051这种十六进制数,就改成"%x"

关于大佬解题wp的疑惑

大佬代码

 1 key = 0xA051
2 num = 2024
3 table = []
4 cmp = [0x9C, 0xCC, 0x88, 0x76, 0xD7, 0x89, 0x78, 0xEC, 0x7C, 0xD7, 0x89, 0x71, 0xE3, 0x6D, 0x98, 0x17, 0x94, 0x0F, 0xCA, 0x9F, 0x7E, 0xD9, 0xA0, 0x8A, 0x79, 0xD1, 0x80, 0x77]
5
6 tb = 0
7 flag = []
8 for i in range(28):
9 ta = key + num + tb
10 flag.append((cmp[i] - (ta&0xff)) & 0xff)
11 tb = (ta >> 4) ^ cmp[i]
12 print(''.join(chr(i) for i in flag))

flag.append((cmp[i] - (ta&0xff)) & 0xff)——这一部分的我没看懂

ta是偏移量,加密代码里是与偏移量相加,解题脚本里面就相减,这我能理解

(ta&0xff)) & 0xff——这个我就不太理解为什么这样写

以下是关于疑问的解答(参考:C语言的整数溢出机制 - 知乎 (zhihu.com)

ta&0xff——提取了ta中的最低8位,为了获取一个有效字节值(8位)

为什么是8位?

首先这是一个无符号位char类型数对于signed char,正整数最大值为127,负整数最小值为128。unsigned char所能表示的最大值为255。

有符号整型溢出又可分为向上溢出和向下溢出。假设用k个字节表示一个整型变量, 那么这个变量可以表示的有符号整数的范围是-2^(8k-1) ~ 2^(8k-1) – 1

那么两个正整数或者两个负整数相加就有可能超过这个整型变量所能表示的范围

向上超出>2^(8k-1) – 1我们称之为向上溢出

向下超出<-2^(8k-1), 我们称之为向下溢出

无论是向上溢出还是向下溢出,绝对值都在相对于无符号整型能表示的范围内————对于signed char,如果结果为400,超出了位数表示范围,取结果的低八位

& 0xff——这个操作是为了确保结果在一个字节范围内(0到255),因为解密的结果应该是一个字节

那可以去掉吗?

GPT回答:

在这种情况下,去掉 `(ta&0xff)` 后的 `& 0xff` 是可能的,但是需要对解密结果的范围进行一些考虑。

`(ta&0xff)` 的目的是确保偏移量 `ta` 的范围在0到255之间,因为偏移量是一个字节(8位)的值。在实际应用中,这个操作可以确保解密结果在0到255之间,即一个字节的范围内。

如果你确定在加密过程中偏移量的计算不会导致超出一个字节的范围(例如,`key`、`num` 和 `tb` 的取值都在合适的范围内),那么去掉 `(ta&0xff)` 后的 `& 0xff` 是可以的。

但是,如果你不确定加密过程中的偏移量是否会超出一个字节的范围,保留 `& 0xff` 可以确保解密结果始终在合适的范围内,这样更加安全可靠。


flag

ctfshow{happy_2024_jiayou_a}

re_signin 【ctfshow_元旦水友赛】Reserve的更多相关文章

  1. 第一次线上OJ水友赛

    偶然的机会遇到了这个神奇的网站http://www.luogu.org/   巧遇今天又有小比赛果断去试试,为我的蓝桥北京之旅练练手. 苦苦的在机房刷了一下午,大概做到了6点半. 最激动的是等成绩了, ...

  2. 【题解】LFYZNoip前水题赛 T6

    垃圾出题人们在30分钟内完成了讨论,出题,命题,造数据,跑std的所有环节 luv的化学竞赛题 题目背景 luv_letters 在肝化学竞赛题,他的梦想是混个省一,但是遗憾的是他今年的省二莫名消失了 ...

  3. 0RAYS元旦招新赛

    一共有4道pwn题,题目不算难,但是挺考验调试能力的. pie 一个main函数就四次溢出... 第一次leak canary,第二次leak libc,第三次直接覆盖返回地址为one_gadgets ...

  4. 【Cocos2d-x游戏引擎开发笔记(25)】XML解析

    原创文章,转载请注明出处:http://blog.csdn.net/zhy_cheng/article/details/9128819 XML是一种非常重要的文件格式,由于C++对XML的支持非常完善 ...

  5. CQOI2019(十二省联考)游记

    CQOI2019(十二省联考)游记 Day -? 自从联赛爆炸,\(THUWC\)爆炸,\(WC\)爆炸(就没有不爆炸的)之后我已经无所畏惧... 听说是考\(4.5 h\)吗? Day -1 \(Z ...

  6. 魔兽争霸RPG游戏-军团战争-游戏经验总结

    终于要写这篇了,上一篇是个意外. 2015年关注,一代鬼王Xun和GGL比赛.晚上11点之后,经常有水友赛.主播xun,会带着一帮小弟,玩一些游戏.比如魔兽争霸6v6,2v2,RPG游戏-军团战争,疯 ...

  7. 【集训第二天·翻水的老师】--ac自动机+splay树

    今天是第二天集训.(其实已经是第三天了,只是昨天并没有机会来写总结,现在补上) 上午大家心情都很愉快,因为老师讲了splay树和ac自动机. 但到了下午,我们的教练竟然跑出去耍了(excuse me? ...

  8. dota有哪些经典的典故或笑话?

    ----------------------------------------------------dota有哪些经典的典故或笑话?虽然现在玩游戏也没什么热情了, 但是看到这些还是笑尿,笑点低 = ...

  9. 聚光灯下的熊猫TV技术架构演进

    2015年开始的百播大战,熊猫TV是其中比较特别的一员. 说熊猫TV是含着金钥匙出生的公子哥不为过.还未上线,就频频曝光,科技号,微博稿,站上风口浪尖.内测期间更是有不少淘宝店高价倒卖邀请码,光内测时 ...

  10. 【网络可靠版】Extjs4 Treegrid 使用实例

    最近调试EXTJS 4的treegrid实例,看了很多水友的文章,以及官方的demo, 没一个可靠的,全都无法显示出来.像对于我们习惯用C++的coder来说,EXTJS简直就是一群无政府土匪来维护的 ...

随机推荐

  1. NEMU PA 3-3 实验报告

    一.实验目的 在上一章PA3-2中,我们实现了分段机制,将48位的虚拟地址vaddr转换成了laddr.为什么不是paddr呢?这就要说到这一章要完成的东西:**分页机制 **. 从80386开始,计 ...

  2. linux下使用find查找并操作文件

    介绍 最近在centos7上部署了一套环境,需要根据文件名找到程序运行路径下的文件,并进行移动文件操作,为此查阅了一番,记录下这个操作的脚本.我想很多人都会有这个需求,查找简单,但是要对对查找到的文件 ...

  3. Annotation-specified bean name conflicts with existing

    问题说明 Annotation-specified bean name conflicts with existing,non-compatible bean definition of same n ...

  4. Spring Security实现JDBC用户登录认证

    在搭建博客后端服务框架时,我采用邮件注册+Spring Security登录认证方式,结合mysql数据库,给大家展示下具体是怎么整合的. 本篇是基于上一篇:spring boot实现邮箱验证码注册 ...

  5. Aop @AfterReturning因返回类型不一致导致无法执行切面代码

    要做返回异常之后,所有操作回滚的操作,本来想着泛型用 Object 就表示所有返回类型是 CommonResult 并且加指定注解的都走这个通知的代码,但是如下配置,无论如何也不生效 进入源码里发现, ...

  6. h5页面在微信打开,ios底部存在返回横条的问题

    我的问题比较简单,一个处理链接的页面,二次跳转进入真正的页面,导致ios出现返回横条,点击后退回到了处理链接页面.因为这个后退不会重新加载,导致一直处在处理链接的这个空页面. 所以我用replace代 ...

  7. centos7.x及centos8.x安装新版docker

    前置步骤 # 如之前安装过docker,请先删除 yum remove docker docker-common docker-selinux docker-engine centos7 # cent ...

  8. 【MongoDB】C# .Net MongoDB常用语法

    1.1.驱动安装 使用NuGet包管理器安装MongoDB C#驱动:MongoDB.Driver 1.2. C#连接MongoDB //获取MongoDB连接客户端 MongoClient clie ...

  9. 【Azure 服务总线】如何批量删除Azure Service Bus中的Topics(数量较多,需要过滤后批量删除)

    问题描述 Azure Service Bus 的门户操作页面上,是否可以批量删除其中的Topics呢? 问题解答 Azure Service Bus门户或Service Bus Explorer工具没 ...

  10. 【Azure 应用服务】Azure SignalR 是否可以同时支持近十万人在线互动

    什么是 Azure SignalR 服务? Azure SignalR Service 简化了通过 HTTP 向应用程序添加实时 Web 功能的过程. 这种实时功能允许服务将内容更新推送到连接的客户端 ...