DEATHTOUCH 发表于 2024-2-27 17:17

模仿春节解红包,但是Windows中级题

本帖最后由 DEATHTOUCH 于 2024-2-29 11:36 编辑

今年的春节红包Windows题只有两题,除了几乎等于送分的初级题,就是巨难的高级题,全论坛就几个人做出。

我记得两年前的红包题还有Windows中级题,挺有意思的,所以就像模仿一个题给大伙玩玩。

程序使用mingw32编译,没有加壳,不过gcc优化比较抽象。

一开始忘记strip符号表了,现在附件多了一个strip后的exe,可以对比着看看。

uid可以通过这个连接获取:https://www.52pojie.cn/home.php?mod=space&do=profile

成功截图:



为了沉浸式再体验一次红包题,我就不提供具体的一组key了,不过难度不高得到自己uid的一组key应该比较容易。



解压密码:52pojie

有能力有空的可以搞个注册机(涉及到软浮点,直接看肯定复杂,可以简化)。

源码在 https://gitee.com/peazomboss/softfloat32
有兴趣可以看看,就是套了一下之前的软浮点代码。

爱飞的猫 发表于 2024-2-28 03:19

本帖最后由 爱飞的猫 于 2024-2-28 03:27 编辑

记得把符号抹掉呀!编译器添加参数 `-O2 -s`

应该是利用浮点特性,稍微看了下跟不出来,但是可以把你的 CM 改成注册机;可以参考下面的 1337 补丁文件或直接看我在 x64dbg 下使用 Multiline Ultimate Assembler 写的补丁代码:



```s
<$crackme_2024_2_27.171C>

      mov byte ptr ss:, bl
      nop
      nop
      nop
      nop
      nop
      nop
      nop

<$crackme_2024_2_27.17DC>

      mov byte ptr ss:, bl
      nop
      nop
      nop

<$crackme_2024_2_27.0C17B>
   jmp $crackme_2024_2_27.0C19C
   db 0xE9

<$crackme_2024_2_27.0C1B6>
   @loop_begin:
   movzx eax, byte
   mov dword, eax
   call $crackme_2024_2_27.0BE58 ; putchar
   inc ebx
   cmp ebx, 0x10
   jmp @f
   dd 0x90909090
   @@:
   jl @loop_begin
   jmp $crackme_2024_2_27.0C0CF
```

之后就是执行补丁好的程序,输入 uid,弹出密钥。

```
Input uid: 176017
Input flag: c72cb0c805b0d947
Press any key to continue . . .
```

(这究竟算不算注册机呢…)

---

> 除了几乎等于送分的初级题,就是巨难的高级题,全论坛就几个人做出。

今年的 Windows 高级题现在有去掉了 Themida 壳的版本可以尝试哦!期待你的分析。

oscouregeo 发表于 2024-2-27 19:35

本帖最后由 oscouregeo 于 2024-2-27 19:39 编辑

image.png
16位
image.png
前8位
image.png
后8位
image.png

DEATHTOUCH 发表于 2024-2-28 12:22

本帖最后由 DEATHTOUCH 于 2024-2-28 12:24 编辑

爱飞的猫 发表于 2024-2-28 03:19
记得把符号抹掉呀!编译器添加参数 `-O2 -s`

应该是利用浮点特性,稍微看了下跟不出来,但是可以把 ...
我这个CM就是套了一下之前写的软浮点代码,实际上不难只能唬唬新手,所以叫“中级题”,其实偏初级的。

还有忘记strip了,不过我开的就是O2,不过gcc的优化好抽象。

爱飞的猫 发表于 2024-2-29 10:08

DEATHTOUCH 发表于 2024-2-28 12:22
我这个CM就是套了一下之前写的软浮点代码,实际上不难只能唬唬新手,所以叫“中级题”,其实偏初级的。
...

如果把代码都挪到头文件,打上 `inline` 标记的话,产出的代码应该会比较难看一些。

坏处就是编译时间会增加… 只是 CM 的话应该没啥区别就是。

solly 发表于 2024-3-1 12:47

本帖最后由 solly 于 2024-3-1 12:49 编辑

正向算法还是好处理,只是代码不太好看:

#include <iostream>
#include <math.h>

/* run this program using the console pauser or add your own getch, system("pause") or input loop */
typedef unsigned long long UINT64;
typedef unsigned int UINT32;
typedef unsigned char UINT8;

union IF {
      UINT32 I;
      floatF;
};

UINT32 _STR_PAUSE[] = {0x3E5C8DC9, 0x3E3F03F0, 0x3E666666, 0x3E627627, 0x3E46E46E, 0x0};

UINT32 _HEX_DIG[]   = {0x00039A50, 0x0003AD87, 0x0003C0BE, 0x0003D3F5, 0x0003E72C, 0x0003FA63,
                     0x00040D9A, 0x000420D1, 0x00043408, 0x0004473F, 0x000747D7, 0x00075B0E,
                                           0x00076E45, 0x0007817C, 0x000794B3, 0x0007A7EA };


UINT32 _STR_IN_FLAG[] = {0x35B7BF3E, 0x50F1CF84, 0x526A9220, 0x561878A6, 0x555C1758, 0x178C29C0,
                         0x4B0EC514, 0x4F790CE8, 0x4760DE8E, 0x4BCB2662, 0x2AAE0BAC, 0x178C29C0, 0x0};

UINT32 _STR_IN_UID[]= {0x3EA0697A, 0x3EF1B77C, 0x3EF61C91, 0x3F008CA3, 0x3EFEE6BB, 0x3E0CA29C,
                         0x3F008CA3, 0x3EE6BAC8, 0x3EDBBE14, 0x3E7EE6BB, 0x3E0CA29C,      0x0};


UINT32 _STR_OK[] = {0x3F1F3E7D, 0x3F172E5D, 0x3EB162C6, 0x3E810204, 0x3F73E7D0, 0x3F5FBF7F, 0x3F6BD7AF, 0x3E810204,
                                    0x3F43870E, 0x3F65CB97, 0x3F4B972E, 0x3E810204, 0x3F65CB97, 0x3F53A74F, 0x3F4F9F3E, 0x3F51A347,
                                    0x3F69D3A7, 0x3EB972E6, 0x0};
UINT32 _STR_ERR[] ={0x0078911A, 0x00C73284, 0x00C73284, 0x00C1F48E, 0x00C73284, 0x004CE218, 0x0037EA40, 0x00C3B3E0,
                                    0x00BCB698, 0x00B07B5A, 0x00A97E12, 0x00C8F1D6, 0x00B07B5A, 0x0037EA40, 0x00CAB128, 0x00C73284,
                                    0x00D36DC2, 0x0037EA40, 0x00A97E12, 0x00B3F9FE, 0x00A97E12, 0x00B778A2, 0x00C0353C, 0x005060BC, 0};
                                    
UINT8 _initreciptable8x8[] ={0xF1, 0xD8, 0xC3, 0xB2, 0xA4, 0x98, 0x8D, 0x84};

UINT8 _initreciptable16x8[] = {0xF8, 0xEA, 0xDD, 0xD2, 0xC8, 0xBF, 0xB6, 0xAE, 0xA7, 0xA1, 0x9B, 0x95, 0x90, 0x8B, 0x86, 0x82};

UINT8 _initreciptable8x8_0[] = {0xF1, 0xD8, 0xC3, 0xB2, 0xA4, 0x98, 0x8D, 0x84};

#define MAX_UID 3000000
UINT32 _rng_seed = 0;

void tip_uid();
void tip_flag();
void tip_error();
void tip_ok();
UINT64 _getapproxrecip16x8_32(UINT32 arg);
bool check(UINT32 uid, char * flag);
bool get_flag(UINT32 uid, char * flag);
bool get_flag_part(UINT32 uid_part, char * flag);

int main(int argc, char** argv) {
      printf("Hello world.\n");
      
      //UINT64 ar = _getapproxrecip16x8_32(0x99B80000);
      //printf("ar = %I64X\n", ar);
      
      tip_uid();
      //UINT32 uid = 1024510;      //// "faba9cb5ad6b01f8"
      //UINT32 uid = 1034567;      //// "0d0e487c7a57a036"
      UINT32 uid = 1234567;      //// "2b9f32d2cd6b6f5d"
      printf("%u\n", uid);
      char flag[] = "0123456789ABCDEF\0";

      bool ret = get_flag(uid, flag);
      printf("flag = %s\n", flag);
      
      /*
      tip_flag();
      printf("\n");
      tip_error();
      printf("\n");
      tip_ok();
      printf("\n");
      */

      /*
      if(uid<MAX_UID) {
                bool isOK = check(uid, flag);
                if(isOK) {
                        tip_ok();
                } else {
                        tip_error();
                }
      } else {
                tip_error();
      }
      printf("\n");
      */
      return 0;
}

void tip_uid() {
      IF m1, m2;
      m2.I = 0x3B8CA29C;
      
      int i=0;
      while(_STR_IN_UID != 0) {
                m1.I = _STR_IN_UID;
                float a = ( m1.F / m2.F);
                //int b = round(a);
                int b = trunc(a);
                printf("%c", (char)b);
      }
}

void tip_flag() {
      for(int i=0; i<13; i++) {
                char output_ch = 0;
                int f = _STR_IN_FLAG;
                if(f>12345677) {
                        UINT32 a = 2918332797; // _getapproxrecip16x8_32(12345678 * 256)
                        UINT64 aa = (UINT64)f * a;
                        //printf("aa = %I64X\n", aa);
                        UINT32 ch = (UINT32)(aa >> 55);
                        UINT32 b = f - ch * 12345678;
                        //printf("ch = 0x%x\n", ch);
                        UINT32 c = b;
                        //printf("%u\n", c);
                        output_ch = (char)ch;
                        //printf("ch = %c\n", (char)output_ch);
                        if(b>12345677) {
                              b -= 12345678;
                              UINT64 d = (UINT64)b * 1459166399; /// 1459166398 + 1
                              if((d & 0x40000000000000) == 0) {
                                        output_ch ++;
                              }
                              while(b>12345677) {
                                        b -= 12345678 * 2;
                                        output_ch += 2;
                              }
                              //printf("2: %u\n", output_ch);
                        }
                }
                printf("%c", (char)output_ch);
      }
}

void tip_error() {
      for(int i=0; i<24; i++) {
                char output_ch = 0;
                int e = _STR_ERR;
                if(e>114513) {
                        UINT32 a = 2457996198; // _getapproxrecip16x8_32(114514 * 32768)
                        UINT64 aa = (UINT64)e * a;
                        //printf("aa = %I64X\n", aa);
                        UINT32 ch = (UINT32)(aa >> 48);
                        UINT32 b = e - ch * 114514;
                        //printf("ch = 0x%x\n", ch);
                        UINT32 c = b;
                        //printf("%u\n", c);
                        output_ch = (char)ch;
                        //printf("ch = %c\n", (char)output_ch);
                        if(b>114513) {
                              b -= 114514;
                              UINT64 d = (UINT64)b * 2457996199;// 2457996198 + 1
                              if((d & 0x40000000000000) == 0) {
                                        output_ch ++;
                              }
                              while(b>114513) {
                                        b -= 114514 * 2;
                                        output_ch += 2;
                              }
                              //printf("2: %u\n", output_ch);
                        }
                }
                printf("%c", (char)output_ch);
      }
}

void tip_ok() {
      IF m1;
      float m2 = 127;
      
      for(int i=0; i<18; i++) {
                m1.I = _STR_OK;
                float a = ( m1.F * m2);
                //int b = round(a);
                int b = trunc(a);
                printf("%c", (char)b);
      }
}

UINT64 _getapproxrecip16x8_32(UINT32 arg) {
      UINT32 a = _initreciptable16x8 * 0x1000000;
      UINT64 b = -(UINT32)(((UINT64)a * arg) >> 32);
      UINT64 c = ((b * a)>>32) * 2;
      UINT32 d = -((arg * c) >> 32);
      UINT64 e = d * c;
      UINT64 f = (e >> 32) * 2;
      UINT32 g = (UINT32)((arg * f)>>32);
      UINT64 h = (~(g)) * f;

      return (h >> 31);
}

void rand_generator(UINT32 seed, UINT32 &rnd1, UINT32 &rnd2) {
      float max_uid = MAX_UID;
      float flt_uid = seed;

      float a = flt_uid / max_uid;
      float b = a - 0.5;
      IF stu_b;
      stu_b.F = b;
      if(b>0) {
                stu_b.I --;
      } else {
                stu_b.I ++;
      }
      float d = stu_b.F;
      UINT32 d2 = stu_b.I;

      IF stu_e;
      stu_e.I = 0x3C9D89D9; /// 0.01923076994717121
      float e = stu_e.F;
      float f = e * flt_uid;
      //UINT32 g = round(f);
      UINT32 g = trunc(f);
      
      if(f>28846) {
                g /= 2;
      }
      
      UINT32 h = g + 1024;
      IF stu_j;
      stu_j.F = d;
      UINT32 j = stu_j.I;

      if(h>1) {
                int k = 1;
                do {
                        j = j * 134775813 + 1;
                        k++;
                } while(h != k);
      }
      rnd1 = j * 134775813 + 1;            /// 0xC784E0D0
      UINT32 k = rnd1 * 134775813 + 1;
      _rng_seed = k;

      UINT32 u = rnd1 + d2;
      UINT32 v = u + k;
      rnd2 = (v<<16) | (v>>16);
}

bool get_flag(UINT32 uid, char * flag) {
      //// random
      UINT32 rnd1=0, rnd2=0;
      rand_generator(uid, rnd1, rnd2);
      
      //printf("rnd1 = 0x%08X, rnd2 = 0x%08X\n", rnd1, rnd2);
      
      //// part 1
      bool ret1 = get_flag_part(rnd1, &flag);
      
      //// part 2
      bool ret2 = get_flag_part(rnd2, &flag);
      
      return ret1 && ret2;
}

bool get_flag_part(UINT32 uid_part, char * flag) {
      int i = 0;
      do {
                //char ch_a = flag;
                UINT32 flag_ch=0;
                UINT32 p = _HEX_DIG;
                if(p>4918) {
                        UINT64 ar = _getapproxrecip16x8_32(0x99B80000);
                        //UINT32 ar_a = 0xD52B24CA;
                        UINT32 ar_a = (UINT32)(ar);
                        //UINT32 ar_d = 0x6A959265;
                        
                        UINT64 q = (UINT64)p * ar_a;
                        flag_ch = (UINT64)(q >> 44);
                        UINT32 r = (UINT32)(flag_ch * 4919);
                        UINT32 s = p - r;
                        if(s>4918) {
                              s -= 4919;
                              UINT64 t = (UINT64)s * 894093619;
                              
                              if(( t & 0x040000000000) == 0) {
                                        flag_ch ++;
                                        if(s>4918) {
                                                do {
                                                      s -= 9838;
                                                      flag_ch+=2;
                                                } while(s > 4918);
                                        }
                              }
                        }
                }
                uid_part = uid_part / 16; /// l>>=4;
                //printf("%c", flag_ch);
                flag = (char)flag_ch;
                i++;
      } while(i<8);
      
      return true;
}

bool check(UINT32 uid, char * flag) {
      return true;
}

solly 发表于 2024-3-1 13:09

有3个除法的代码,美化了一下:

#include <iostream>
#include <math.h>

/* run this program using the console pauser or add your own getch, system("pause") or input loop */
typedef unsigned long long UINT64;
typedef unsigned int UINT32;
typedef unsigned char UINT8;

union IF {
        UINT32 I;
        floatF;
};

UINT32 _STR_PAUSE[] = {0x3E5C8DC9, 0x3E3F03F0, 0x3E666666, 0x3E627627, 0x3E46E46E, 0x0};

UINT32 _HEX_DIG[]   = {0x00039A50, 0x0003AD87, 0x0003C0BE, 0x0003D3F5, 0x0003E72C, 0x0003FA63,
                     0x00040D9A, 0x000420D1, 0x00043408, 0x0004473F, 0x000747D7, 0x00075B0E,
                                           0x00076E45, 0x0007817C, 0x000794B3, 0x0007A7EA };


UINT32 _STR_IN_FLAG[] = {0x35B7BF3E, 0x50F1CF84, 0x526A9220, 0x561878A6, 0x555C1758, 0x178C29C0,
                         0x4B0EC514, 0x4F790CE8, 0x4760DE8E, 0x4BCB2662, 0x2AAE0BAC, 0x178C29C0, 0x0};

UINT32 _STR_IN_UID[]= {0x3EA0697A, 0x3EF1B77C, 0x3EF61C91, 0x3F008CA3, 0x3EFEE6BB, 0x3E0CA29C,
                         0x3F008CA3, 0x3EE6BAC8, 0x3EDBBE14, 0x3E7EE6BB, 0x3E0CA29C,      0x0};


UINT32 _STR_OK[] = {0x3F1F3E7D, 0x3F172E5D, 0x3EB162C6, 0x3E810204, 0x3F73E7D0, 0x3F5FBF7F, 0x3F6BD7AF, 0x3E810204,
                                    0x3F43870E, 0x3F65CB97, 0x3F4B972E, 0x3E810204, 0x3F65CB97, 0x3F53A74F, 0x3F4F9F3E, 0x3F51A347,
                                    0x3F69D3A7, 0x3EB972E6, 0x0};
UINT32 _STR_ERR[] ={0x0078911A, 0x00C73284, 0x00C73284, 0x00C1F48E, 0x00C73284, 0x004CE218, 0x0037EA40, 0x00C3B3E0,
                                    0x00BCB698, 0x00B07B5A, 0x00A97E12, 0x00C8F1D6, 0x00B07B5A, 0x0037EA40, 0x00CAB128, 0x00C73284,
                                    0x00D36DC2, 0x0037EA40, 0x00A97E12, 0x00B3F9FE, 0x00A97E12, 0x00B778A2, 0x00C0353C, 0x005060BC, 0};
                                   
UINT8 _initreciptable8x8[] ={0xF1, 0xD8, 0xC3, 0xB2, 0xA4, 0x98, 0x8D, 0x84};

UINT8 _initreciptable16x8[] = {0xF8, 0xEA, 0xDD, 0xD2, 0xC8, 0xBF, 0xB6, 0xAE, 0xA7, 0xA1, 0x9B, 0x95, 0x90, 0x8B, 0x86, 0x82};

UINT8 _initreciptable8x8_0[] = {0xF1, 0xD8, 0xC3, 0xB2, 0xA4, 0x98, 0x8D, 0x84};

#define MAX_UID 3000000
UINT32 _rng_seed = 0;

void tip_uid();
void tip_flag();
void tip_error();
void tip_ok();
UINT64 _getapproxrecip16x8_32(UINT32 arg);
bool check(UINT32 uid, char * flag);
bool get_flag(UINT32 uid, char * flag);
bool get_flag_part(UINT32 uid_part, char * flag);

int main(int argc, char** argv) {
        printf("Hello world.\n");
       
        //UINT64 ar = _getapproxrecip16x8_32(0x99B80000);
        //printf("ar = %I64X\n", ar);
       
        tip_uid();
        //UINT32 uid = 1024510;      //// "faba9cb5ad6b01f8"
        //UINT32 uid = 1034567;      //// "0d0e487c7a57a036"
        UINT32 uid = 1234567;      //// "2b9f32d2cd6b6f5d"
        printf("%u\n", uid);
        char flag[] = "0123456789ABCDEF\0";

        bool ret = get_flag(uid, flag);
        printf("flag = %s\n", flag);
       
        ///*
        tip_flag();
        printf("\n");
        tip_error();
        printf("\n");
        tip_ok();
        printf("\n");
        //*/

        /*
        if(uid<MAX_UID) {
                bool isOK = check(uid, flag);
                if(isOK) {
                        tip_ok();
                } else {
                        tip_error();
                }
        } else {
                tip_error();
        }
        printf("\n");
        */
        return 0;
}

void tip_uid() {
        IF m1, m2;
        m2.I = 0x3B8CA29C;
       
        int i=0;
        while(_STR_IN_UID != 0) {
                m1.I = _STR_IN_UID;
                float a = ( m1.F / m2.F);
                //int b = round(a);
                int b = trunc(a);
                printf("%c", (char)b);
        }
}

void tip_flag() {
        for(int i=0; i<13; i++) {
                char output_ch = _STR_IN_FLAG / 12345678;
                printf("%c", (char)output_ch);
        }
}

void tip_error() {
        for(int i=0; i<24; i++) {
                char output_ch = _STR_ERR / 114514;
                printf("%c", (char)output_ch);
        }
}

void tip_ok() {
        IF m1;
        float m2 = 127;
       
        for(int i=0; i<18; i++) {
                m1.I = _STR_OK;
                float a = ( m1.F * m2);
                //int b = round(a);
                int b = trunc(a);
                printf("%c", (char)b);
        }
}

UINT64 _getapproxrecip16x8_32(UINT32 arg) {
        UINT32 a = _initreciptable16x8 * 0x1000000;
        UINT64 b = -(UINT32)(((UINT64)a * arg) >> 32);
        UINT64 c = ((b * a)>>32) * 2;
        UINT32 d = -((arg * c) >> 32);
        UINT64 e = d * c;
        UINT64 f = (e >> 32) * 2;
        UINT32 g = (UINT32)((arg * f)>>32);
        UINT64 h = (~(g)) * f;

        return (h >> 31);
}

void rand_generator(UINT32 seed, UINT32 &rnd1, UINT32 &rnd2) {
        float max_uid = MAX_UID;
        float flt_uid = seed;

        float a = flt_uid / max_uid;
        float b = a - 0.5;
        IF stu_b;
        stu_b.F = b;
        if(b>0) {
                stu_b.I --;
        } else {
                stu_b.I ++;
        }
        float d = stu_b.F;
        UINT32 d2 = stu_b.I;

        IF stu_e;
        stu_e.I = 0x3C9D89D9; /// 0.01923076994717121
        float e = stu_e.F;
        float f = e * flt_uid;
        //UINT32 g = round(f);
        UINT32 g = trunc(f);
       
        if(f>28846) {
                g /= 2;
        }
       
        UINT32 h = g + 1024;
        IF stu_j;
        stu_j.F = d;
        UINT32 j = stu_j.I;

        if(h>1) {
                int k = 1;
                do {
                        j = j * 134775813 + 1;
                        k++;
                } while(h != k);
        }
        rnd1 = j * 134775813 + 1;            /// 0xC784E0D0
        UINT32 k = rnd1 * 134775813 + 1;
        _rng_seed = k;

        UINT32 u = rnd1 + d2;
        UINT32 v = u + k;
        rnd2 = (v<<16) | (v>>16);
}

bool get_flag(UINT32 uid, char * flag) {
        //// random
        UINT32 rnd1=0, rnd2=0;
        rand_generator(uid, rnd1, rnd2);
       
        //// part 1
        bool ret1 = get_flag_part(rnd1, &flag);
       
        //// part 2
        bool ret2 = get_flag_part(rnd2, &flag);
       
        return ret1 && ret2;
}

bool get_flag_part(UINT32 uid_part, char * flag) {
        int i = 0;
        do {
                //char ch_a = flag;
                UINT32 flag_ch = _HEX_DIG / 4919;
                uid_part = uid_part / 16; /// l>>=4;
                //printf("%c", flag_ch);
                flag = (char)flag_ch;
                i++;
        } while(i<8);
       
        return true;
}

bool check(UINT32 uid, char * flag) {
        return true;
}



页: [1]
查看完整版本: 模仿春节解红包,但是Windows中级题