diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..452ce3c Binary files /dev/null and b/.DS_Store differ diff --git a/official/.DS_Store b/official/.DS_Store new file mode 100644 index 0000000..f665caa Binary files /dev/null and b/official/.DS_Store differ diff --git a/official/Flag 计算机/.DS_Store b/official/Flag 计算机/.DS_Store new file mode 100644 index 0000000..27934f5 Binary files /dev/null and b/official/Flag 计算机/.DS_Store differ diff --git a/official/Flag 计算机/README.md b/official/Flag 计算机/README.md index 060d412..815e3ae 100644 --- a/official/Flag 计算机/README.md +++ b/official/Flag 计算机/README.md @@ -1 +1,53 @@ # Flag 计算机 + +此题目基于 [https://github.com/skeeto/dosdefender-ld31](https://github.com/skeeto/dosdefender-ld31) 修改而成。 + +``` +由于我太菜了,所以引入了一个 BUG 导致题目下线修改后上线。给大家带来了不便,十分抱歉。 +``` + +这道题主要想展现的效果是在 DOS 和 Windows 上都能运行的程序。在 Windows 上运行将弹出一个对话框。 +![](./pics/1.png) +这和我们在 DOS 上运行 Windows PE 程序在 DOS 中输出"This program cannot be run in DOS mode"相照应。如果我们把程序载入 010editor就会发现一些猫腻。 +![](pics/2.png) +我们会发现原来的 DOS stub 充满了代码。实际上我是先编译了一个 COM 可执行文件,然后手动为 COM 文件加上 DOS 头。所以在此过程中 DOS 中的一些值是手工进行设置的。 +然后我将能够运行的 DOS 可执行文件设置为 visual studio 2019 中的 exe 的 DOS stub。最终编译成了你们现在看到的样子。 + +## 逆向分析 + +我们将它拖入ida +![](pics/3.png) +我们选择让 IDA 分析 MS-DOS executeble。 +然后我们观察 start 函数。 +![](pics/4.png) +我们发现它调用了一个函数,然后执行了 DOS exit 中断,IDA 已经将其标注了出来。 + +``` +这里用了一个 CPU 指令前缀的编译方法,使得我们的 80386 能够在实模式使用 32 位操作数。0x66 +:它属于 Prefix group 3,Operand-size override prefix。 +``` +有了这样一个 opcode 会有怎么样的行为呢? +![](pics/5.png) +可以看到 operand size 变为了 32bit。 +我们分析 102f 这个函数。 +![](pics/6.png) +可以看到使用了大量使用这个技巧的痕迹,这就是为什么我们能在实模式使用 32bit 寄存器的原因。 + +``` +asm (".code16gcc\n" + "call dosmain\n" + "mov $0x4C,%ah\n" + "int $0x21\n"); +``` +最先展开的 include 项目中有我们的 init.h 。 +这个文件中的一个伪指令 ".code16cc" 代表着让gcc生成 16bit realmode 模式的汇编指令。所以这是为什么大量指令前都有 0x66 的原因。当我们的操作数是类似于 uint32 声明时,0x66 就会起作用。 +逆向的核心过程就是明白程序干了哪些事情,橙色的操作数代表着地址,我们将鼠标悬停在上面,然后右键把它类型转换一下。 +![](pics/7.png) +IDA 就能识别字符串了。 +ps: 作为一个CTF玩家,我最喜欢的事情就是按 F5 ,hackergame 是为了让人能学到东西,而不是千篇一律的难题,不是为了难而难。所以我程序在 realmode 下,IDA 失效了,这样大家都能从 “0” 接触汇编。 +显而易见的是,参数是字符串的一般就是我们的类似的 printf 函数。只不过这里是 vga 的输出而已。 +![](pics/8.png) +我们看整个控制流,发现程序并不复杂,大多数都是控制显示的逻辑。 +大家可以对着源代码再看一遍,这个函数就是对应的 main 函数。 + +下面讲下程序的核心逻辑。 \ No newline at end of file diff --git a/official/Flag 计算机/pics/.DS_Store b/official/Flag 计算机/pics/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/official/Flag 计算机/pics/.DS_Store differ diff --git a/official/Flag 计算机/pics/1.png b/official/Flag 计算机/pics/1.png new file mode 100644 index 0000000..a19e0a7 Binary files /dev/null and b/official/Flag 计算机/pics/1.png differ diff --git a/official/Flag 计算机/pics/2.png b/official/Flag 计算机/pics/2.png new file mode 100644 index 0000000..69b819d Binary files /dev/null and b/official/Flag 计算机/pics/2.png differ diff --git a/official/Flag 计算机/pics/3.png b/official/Flag 计算机/pics/3.png new file mode 100644 index 0000000..d5b328a Binary files /dev/null and b/official/Flag 计算机/pics/3.png differ diff --git a/official/Flag 计算机/pics/4.png b/official/Flag 计算机/pics/4.png new file mode 100644 index 0000000..bf56e4c Binary files /dev/null and b/official/Flag 计算机/pics/4.png differ diff --git a/official/Flag 计算机/pics/5.png b/official/Flag 计算机/pics/5.png new file mode 100644 index 0000000..1f7344d Binary files /dev/null and b/official/Flag 计算机/pics/5.png differ diff --git a/official/Flag 计算机/pics/6.png b/official/Flag 计算机/pics/6.png new file mode 100644 index 0000000..0bb706b Binary files /dev/null and b/official/Flag 计算机/pics/6.png differ diff --git a/official/Flag 计算机/pics/7.png b/official/Flag 计算机/pics/7.png new file mode 100644 index 0000000..588b375 Binary files /dev/null and b/official/Flag 计算机/pics/7.png differ diff --git a/official/Flag 计算机/pics/8.png b/official/Flag 计算机/pics/8.png new file mode 100644 index 0000000..0bb6efb Binary files /dev/null and b/official/Flag 计算机/pics/8.png differ diff --git a/official/Flag 计算机/src/.DS_Store b/official/Flag 计算机/src/.DS_Store new file mode 100644 index 0000000..6af7719 Binary files /dev/null and b/official/Flag 计算机/src/.DS_Store differ diff --git a/official/Flag 计算机/src/get_flag_system/.gitignore b/official/Flag 计算机/src/get_flag_system/.gitignore new file mode 100644 index 0000000..78edc0f --- /dev/null +++ b/official/Flag 计算机/src/get_flag_system/.gitignore @@ -0,0 +1,2 @@ +*.com +*.o diff --git a/official/Flag 计算机/src/get_flag_system/Makefile b/official/Flag 计算机/src/get_flag_system/Makefile new file mode 100644 index 0000000..0f9f3e1 --- /dev/null +++ b/official/Flag 计算机/src/get_flag_system/Makefile @@ -0,0 +1,20 @@ +CC = gcc +DOS = dosbox +CFLAGS = -std=gnu99 -w -O0 -nostdlib -m32 -march=i386 \ + -Wno-unused-function \ + -ffreestanding -fomit-frame-pointer -fwrapv -fno-strict-aliasing \ + -fno-leading-underscore -fno-pic -fno-stack-protector \ + -Wl,--nmagic,-static,-Tcom.ld + +dosdef.com : dosdef.c *.h + +.PHONY : all clean test + +clean : + $(RM) *.com + +test : dosdef.com + $(DOS) $^ + +%.com : %.c + $(CC) -o $@ $(CFLAGS) $< diff --git a/official/Flag 计算机/src/get_flag_system/README.md b/official/Flag 计算机/src/get_flag_system/README.md new file mode 100644 index 0000000..42e684a --- /dev/null +++ b/official/Flag 计算机/src/get_flag_system/README.md @@ -0,0 +1,14 @@ +--- +enabled: true +name: Flag 计算机 +category: binary +url: files/get_flag_system.exe +index: 270 +flags: +- name: '' + score: 300 + type: text + flag: flag{g3tfl4g_0p3r4t1ng_syst3m} +--- + +一个玄学的 flag 计算机,平常的时候只会摸鱼,但如果在**合适的时间**运行它的话,它就可以告诉你真正的 flag。 diff --git a/official/Flag 计算机/src/get_flag_system/UNLICENSE b/official/Flag 计算机/src/get_flag_system/UNLICENSE new file mode 100644 index 0000000..68a49da --- /dev/null +++ b/official/Flag 计算机/src/get_flag_system/UNLICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/official/Flag 计算机/src/get_flag_system/alloc.h b/official/Flag 计算机/src/get_flag_system/alloc.h new file mode 100644 index 0000000..ede7e7f --- /dev/null +++ b/official/Flag 计算机/src/get_flag_system/alloc.h @@ -0,0 +1,23 @@ +#ifndef ALLOC_H +#define ALLOC_H + +#include "int.h" + +extern char _heap; +static char *hbreak = &_heap; + +static void *sbrk(size_t size) +{ + char *ptr = hbreak; + for (size_t i = 0; i < size; i++) + ptr[i] = 0; + hbreak += size; + return ptr; +} + +static void free(void) +{ + hbreak = &_heap; +} + +#endif diff --git a/official/Flag 计算机/src/get_flag_system/com.ld b/official/Flag 计算机/src/get_flag_system/com.ld new file mode 100644 index 0000000..32fa5dd --- /dev/null +++ b/official/Flag 计算机/src/get_flag_system/com.ld @@ -0,0 +1,16 @@ +OUTPUT_FORMAT(binary) +SECTIONS +{ + . = 0x0100; + .text : + { + *(.text); + } + .data : + { + *(.data); + *(.bss); + *(.rodata); + } + _heap = ALIGN(4); +} diff --git a/official/Flag 计算机/src/get_flag_system/dosbox.conf b/official/Flag 计算机/src/get_flag_system/dosbox.conf new file mode 100755 index 0000000..3eee5f0 --- /dev/null +++ b/official/Flag 计算机/src/get_flag_system/dosbox.conf @@ -0,0 +1,10 @@ +# Suggested DOSBox configuration for DOS Defender +# Usage: dosbox -conf dosbox.conf dosdef.com + +[sdl] +output=opengl +windowresolution=1280x800 + +[cpu] +core=dynamic +cycles=max diff --git a/official/Flag 计算机/src/get_flag_system/dosdef.c b/official/Flag 计算机/src/get_flag_system/dosdef.c new file mode 100644 index 0000000..fe82638 --- /dev/null +++ b/official/Flag 计算机/src/get_flag_system/dosdef.c @@ -0,0 +1,261 @@ +#include "init.h" +#include "print.h" +#include "joystick.h" +#include "vga.h" +#include "rand.h" +#include "time.h" +#include "alloc.h" +#include "keyboard.h" +#include "speaker.h" + +#define SCALE 1000 +#define BACKGROUND 17 +#define PLAYER 14 +#define BULLET_SPEED 3 +#define PARTICLE_MAX_AGE 50 +#define MAX_PLAYERS 2 + +typedef unsigned int tick_t; +typedef void (*ai_t)(int id); +typedef void (*power_t)(int id); + +static tick_t ticks; +static unsigned score; +static unsigned best_score; +static struct speaker speaker; + +struct ship { + int32_t x, y, dx, dy; + tick_t last_fire; + ai_t ai; + struct sample *fx_fire; + uint16_t score; + uint16_t hp, hp_max; + uint8_t radius; + uint8_t fire_delay; + uint8_t fire_damage; + uint8_t drop_rate; + uint8_t color_a, color_b; + bool is_player; + union { + int target_ship; + struct { + uint32_t x, y; + } target_position; + }; +}; + +struct bullet { + int32_t x, y, dx, dy; + tick_t birthtick; + uint8_t color; + uint8_t damage; + bool alive; +}; + +struct particle { + int32_t x, y; + tick_t birthtick; + bool alive; +}; + +struct powerup { + int32_t x, y; + tick_t birthtick; + power_t power; + bool alive; + uint8_t color; +}; + +static struct bullet *bullets; +static size_t bullets_max = 32; + +static struct particle *particles; +static size_t particles_max = 64; + +static struct ship *ships; +static size_t ships_max = 12; + +static struct powerup *powerups; +static size_t powerups_max = 8; + +static bool joystick_detected() +{ + struct joystick joystick; + joystick_read(&joystick); + return joystick.axis[0] != 0 || joystick.axis[1] != 0; +} + +static void burn(int32_t x, int32_t y); +static void ship_draw(int id, bool clear); +static void powerup_random(int id); + + +// #define VGA_PWIDTH 320 +// #define VGA_PHEIGHT 200 +// 53 character a line + +static unsigned short strlen(const char * in) +{ + short ret=0; + while(in[ret] != 0) + { + ret++; + } + return ret; +} + +static unsigned short str_line_middle(unsigned short length) +{ + return (53 - length) / 2 * 6; +} + +static void delay() +{ + for(unsigned short i = 0; i<0xf;i++) + { + usleep(800); + } +} + + +// static uint32_t rand_seed = 375226057; + +// static uint32_t rand(void) +// { +// rand_seed = rand_seed * 1103515245 + 12345; +// return rand_seed; +// } + +// static uint32_t randn(uint32_t n) +// { +// return (rand() >> 7) % n; +// } + + + + +uint32_t a,x0,b; + +static uint32_t gen_random_a() +{ + a = get_time() % 58379; + // a = 26141; + x0 = 1103515245; +} + +static uint32_t myrand(void) +{ + x0 = x0 * a + 12345678; + return x0; +} + +// flag{g3tfl4g_0p3r4t1ng_syst3m} +uint32_t get_matrix[15]; +uint32_t my_matrix[15*15]={20597,19141,29258,17804,29076,28746,24890,28979,26196,31833,26624,24774,18916,29028,24033,22913,23436,25750,26539,21652,31296,22446,16506,21949,22761,30221,29477,29617,16497,23022,23179,30781,23877,29171,31665,26534,32159,22583,27525,28708,31216,17158,31988,32190,23747,21272,21278,24727,29984,25303,23445,23119,23155,26346,26389,30747,28948,31418,21323,31758,30911,18790,21312,25099,22348,25409,29357,22180,23588,28794,18133,25624,21972,23401,24821,31369,25187,31517,19840,28836,20794,20239,24523,30814,24016,17954,21227,16691,30290,23391,20482,24822,31968,30651,27908,22690,30875,31003,31747,19978,25482,18563,30143,27788,26658,26295,23244,27086,26456,24251,28647,22783,27460,19187,23252,24078,19203,26251,18113,19542,24533,16666,24038,32744,28670,30438,26379,18591,30109,26509,20947,27696,22945,27542,32128,25416,21675,19389,27085,29380,20163,21102,30936,30862,18230,21904,16938,16579,20641,27551,22740,24666,16836,23306,27661,26506,28623,29816,20166,29405,23982,30046,19365,24926,19029,32448,17567,17156,18678,28594,19769,28631,25769,31309,24457,30625,21825,29811,17112,31370,25345,24333,24005,31606,30942,21441,30599,22894,18015,19994,27901,26868,21948,27614,23449,21289,19588,19955,28133,16696,31509,26219,19946,27895,28760,28547,28315,16614,26006,17129,24769,24608,17714,17682,18532,17597,29247,28789,27011,29841,32640,17508,27662,23548,29514}; + + +int dosmain(void) +{ + + vga_on(); + vga_clear(BACKGROUND); + vga_vsync(); + + vga_print((struct point){str_line_middle(strlen("WWWWWWWWWWWWWOOOOOOOOOOWWWWWOO OOOOOOOWWWWWWWWWWWWWWW")), 14}, MAGENTA, "WWWWWWWWWWWWWOOOOOOOOOOWWWWWOO OOOOOOOWWWWWWWWWWWWWWW"); + vga_print((struct point){str_line_middle(strlen("WWWWWWWWOOO OONWWWWWOOO OOOWWWWWWWWWW")), 23}, MAGENTA, "WWWWWWWWOOO OONWWWWWOOO OOOWWWWWWWWWW"); + vga_print((struct point){str_line_middle(strlen("WWWWWWOOO OOOdOOWWWWMMWOOdOOO OdOWWWWWWWW")), 32}, MAGENTA, "WWWWWWOOO OOOdOOWWWWMMWOOdOOO OdOWWWWWWWW"); + vga_print((struct point){str_line_middle(strlen("WWWWWOO OOdONWOOOdOOOOOdOOOWNOOO OOWWWWWWW")), 41}, MAGENTA, "WWWWWOO OOdONWOOOdOOOOOdOOOWNOOO OOWWWWWWW"); + vga_print((struct point){str_line_middle(strlen("WWWNOO OONWOOOOO OOOOOWOOO OOWWWWWW")), 50}, MAGENTA, "WWWNOO OONWOOOOO OOOOOWOOO OOWWWWWW"); + vga_print((struct point){str_line_middle(strlen("WWWOO OOOWOOO OdOWOOO OOWWWWW")), 59}, MAGENTA, "WWWOO OOOWOOO OdOWOOO OOWWWWW"); + vga_print((struct point){str_line_middle(strlen("WWOO OONWOO OOWNdO OOWWWW")), 68}, MAGENTA, "WWOO OONWOO OOWNdO OOWWWW"); + vga_print((struct point){str_line_middle(strlen("WNO OONWOO OOWNOO OONWWW")), 77}, MAGENTA, "WNO OONWOO OOWNOO OONWWW"); + vga_print((struct point){str_line_middle(strlen("WOO OOWOO OOWOO OOMWW")), 86}, MAGENTA, "WOO OOWOO OOWOO OOMWW"); + vga_print((struct point){str_line_middle(strlen("WOO OOMOO OOWOO OOWWW")), 95}, MAGENTA, "WOO OOMOO OOWOO OOWWW"); + vga_print((struct point){str_line_middle(strlen("WOO OOWNdO OOWWOO ONMWO")), 104}, MAGENTA, "WOO OOWNdO OOWWOO ONMWO"); + vga_print((struct point){str_line_middle(strlen("WWOO OOWOOO OdNWOO OOWWWO")), 113}, MAGENTA, "WWOO OOWOOO OdNWOO OOWWWO"); + vga_print((struct point){str_line_middle(strlen("WWNOO OOWNOO OOOWNOO OdNMWWW")), 122}, MAGENTA, "WWNOO OOWNOO OOOWNOO OdNMWWW"); + vga_print((struct point){str_line_middle(strlen("WWWOOO OOOWOOOO OOONWOOO OONWWWWW")), 131}, MAGENTA, "WWWOOO OOOWOOOO OOONWOOO OONWWWWW"); + vga_print((struct point){str_line_middle(strlen("WWWWOdO OOONWOOdOOOOOOOOOdOOWNOOO OdNWWWWWW")), 140}, MAGENTA, "WWWWOdO OOONWOOdOOOOOOOOOdOOWNOOO OdNWWWWWW"); + vga_print((struct point){str_line_middle(strlen("WWWWWNOOO OOOOOOWWNNNNWWNOOOOOO OOOWWWWWWWW")), 149}, MAGENTA, "WWWWWNOOO OOOOOOWWNNNNWWNOOOOOO OOOWWWWWWWW"); + vga_print((struct point){str_line_middle(strlen("WWWWWWWOOOO OOdNWWWWMNdOO OOONWWWWWWWWW")), 158}, MAGENTA, "WWWWWWWOOOO OOdNWWWWMNdOO OOONWWWWWWWWW"); + vga_print((struct point){str_line_middle(strlen("WWWWWWWWWWWWOOOOOO OOMWWWWOO OOOOOOWWWWWMWWWWWWWW")), 167}, MAGENTA, "WWWWWWWWWWWWOOOOOO OOMWWWWOO OOOOOOWWWWWMWWWWWWWW"); + vga_print((struct point){str_line_middle(strlen("WWWWWWWWWWWWWWWNOOOOOONWWWWWNOOdOOONWWWWWWWWWWWWWWWWW")), 176}, MAGENTA, "WWWWWWWWWWWWWWWNOOOOOONWWWWWNOOdOOONWWWWWWWWWWWWWWWWW"); + delay(); + vga_clear(BACKGROUND); + gen_random_a(); + uint32_t rand_gen[15]; + for(uint32_t i=0;i<15;i++) + { + rand_gen[i] = myrand(); + } + for(uint32_t i=0;i<15;i++) + { + for(uint32_t j=0;j<15;j++) + { + get_matrix[i] += (my_matrix[i*15+j] * rand_gen[j]) & (0xffff); + get_matrix[i] = get_matrix[i] & 0xffff; + vga_clear(BACKGROUND); + vga_print((struct point){str_line_middle(strlen("GETFLAG OPERATING SYSTEM")), 5}, MAGENTA, "GETFLAG OPERATING SYSTEM"); + vga_print((struct point){0, 15}, MAGENTA, "OPERATING SYSTEM USE AI TECH"); + vga_print((struct point){0, 25}, MAGENTA, "SETTING A RANDOM FLAG SEED"); + vga_print((struct point){0, 35}, RED, "CHECKED YOU ARE PLAYING USTC HACKERGAME"); + vga_print((struct point){0, 45}, MAGENTA, "LET ME COMPUTE FLAG FOR YOU"); + vga_print((struct point){0, 55}, MAGENTA, "IF I FIND THE FLAG I WILL PRINT IT"); + for(short k=0; k<0xff;k++) + { + vga_print((struct point){0, 65}, RED, "COMPUTING PLEASE WAIT"); + usleep(800); + vga_print((struct point){0, 65}, BLACK, "COMPUTING PLEASE WAIT"); + usleep(800); + } + } + } + vga_clear(BACKGROUND); + vga_print((struct point){str_line_middle(strlen("GETFLAG OPERATING SYSTEM")), 5}, MAGENTA, "GETFLAG OPERATING SYSTEM"); + vga_print((struct point){0, 15}, MAGENTA, "FOUND A SOLUTION"); + vga_print((struct point){0, 25}, MAGENTA, "FLAG IS IN PRINTABLE FORMAT"); + vga_print((struct point){0, 35}, MAGENTA, "THE SYSTEM MAY GET WRONG SEED"); + vga_print((struct point){0, 45}, MAGENTA, "YOU SHOULD RESET IT"); + for(int i=0; i < 0xff; i++) + { + for(int j=0; j < 0xa0; j++) + { + + } + } + delay(); + vga_off(); + // 187 49114 12533 39320 44039 25566 22160 10990 15801 27249 45757 55153 58050 7065 14228 + // printl(get_matrix[0]); + // printl(get_matrix[1]); + // printl(get_matrix[2]); + // printl(get_matrix[3]); + // printl(get_matrix[4]); + // printl(get_matrix[5]); + // printl(get_matrix[6]); + // printl(get_matrix[7]); + // printl(get_matrix[8]); + // printl(get_matrix[9]); + // printl(get_matrix[10]); + // printl(get_matrix[11]); + // printl(get_matrix[12]); + // printl(get_matrix[13]); + // printl(get_matrix[14]); + char out[40]; + + out[30] = '$'; + out[31] = '$'; + out[32] = '$'; + out[33] = '$'; + print("\nYOU SHOULD CHECK PRINT OUT STRING ASCII$$"); + print("\nDOS ONLY PRINT UPPERCASE LETTERS$$"); + print("\n$$$$"); + unsigned short aim[30]={221, 49078, 12436, 39423, 44156, 25529, 22179, 10906, 15839, 27165, 45705, 55062, 58013, 7081, 14308, 136, 49064, 12481, 39404, 44086, 25520, 22263, 10929, 15818, 27144, 45774, 55045, 58097, 7156, 14313}; + for(short i=0; i<30;i++) + { + out[i] = (char)(aim[i] ^ get_matrix[i%15]); + } + print(out); + return 0; +} diff --git a/official/Flag 计算机/src/get_flag_system/files/get_flag_system.exe b/official/Flag 计算机/src/get_flag_system/files/get_flag_system.exe new file mode 100644 index 0000000..d275c1e Binary files /dev/null and b/official/Flag 计算机/src/get_flag_system/files/get_flag_system.exe differ diff --git a/official/Flag 计算机/src/get_flag_system/init.h b/official/Flag 计算机/src/get_flag_system/init.h new file mode 100644 index 0000000..bc96013 --- /dev/null +++ b/official/Flag 计算机/src/get_flag_system/init.h @@ -0,0 +1,5 @@ +/* NOTICE: This must be included first! */ +asm (".code16gcc\n" + "call dosmain\n" + "mov $0x4C,%ah\n" + "int $0x21\n"); diff --git a/official/Flag 计算机/src/get_flag_system/int.h b/official/Flag 计算机/src/get_flag_system/int.h new file mode 100644 index 0000000..224d004 --- /dev/null +++ b/official/Flag 计算机/src/get_flag_system/int.h @@ -0,0 +1,18 @@ +#ifndef INT_H +#define INT_H + +typedef unsigned char uint8_t; +typedef char int8_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned long int uint32_t; +typedef long int int32_t; +typedef unsigned long long int uint64_t; +typedef long long int int64_t; +typedef unsigned short size_t; + +#define true 1 +#define false 0 +typedef char bool; + +#endif diff --git a/official/Flag 计算机/src/get_flag_system/joystick.h b/official/Flag 计算机/src/get_flag_system/joystick.h new file mode 100644 index 0000000..3ca33d4 --- /dev/null +++ b/official/Flag 计算机/src/get_flag_system/joystick.h @@ -0,0 +1,88 @@ +#include "math.h" +#include "int.h" + +struct joystick { + uint16_t axis[4]; + bool button[4]; +}; + +struct joystick_config { + uint16_t min[4]; + uint16_t max[4]; + uint16_t center[4]; +}; + +static struct joystick_config joystick_config = { + {0xffff, 0xffff, 0xffff, 0xffff}, + {0x0000, 0x0000, 0x0000, 0x0000}, + {0x0000, 0x0000, 0x0000, 0x0000}, +}; + +static void joystick_read(struct joystick *joystick) +{ + asm volatile ("mov $0x84, %%ah\n" + "mov $1, %%dx\n" + "int $0x15\n" + : "=a"(joystick->axis[0]), "=b"(joystick->axis[1]), + "=c"(joystick->axis[2]), "=d"(joystick->axis[3])); + for (int i = 0; i < 4; i++) { + joystick_config.min[i] = + min(joystick_config.min[i], joystick->axis[i]); + joystick_config.max[i] = + max(joystick_config.max[i], joystick->axis[i]); + } + uint16_t buttons = 0; + asm volatile ("mov $0x84, %%ah\n" + "mov $0, %%dx\n" + "int $0x15\n" + : "=a"(buttons) + : /**/ + : "bx", "cx", "dx"); + for (int i = 0; i < 4; i++) + joystick->button[i] = !(buttons & (1 << (i + 4))); +} + +#include "vga.h" +#include "vga_font.h" + +static void joystick_crosshair(struct point c, uint8_t color) +{ + vga_line((struct point){c.x - 2, c.y}, + (struct point){c.x + 2, c.y}, color); + vga_line((struct point){c.x, c.y - 2}, + (struct point){c.x, c.y + 2}, color); +} + +static void joystick_calibrate() +{ + vga_clear(BLUE); + int32_t scaled[4] = {}; + struct joystick joy; + do { + vga_vsync(); + joystick_crosshair((struct point){scaled[0], scaled[1]}, BLUE); + joystick_crosshair((struct point){scaled[2], scaled[3]}, BLUE); + joystick_read(&joy); + for (int i = 0; i < 4; i++) { + int32_t scale = joystick_config.max[i] - joystick_config.min[i]; + if (scale != 0) { + scaled[i] = joy.axis[i] - joystick_config.min[i]; + scaled[i] *= (i & 0x01) ? VGA_PHEIGHT : VGA_PWIDTH; + scaled[i] /= scale; + } + } + joystick_crosshair((struct point){scaled[0], scaled[1]}, WHITE); + joystick_crosshair((struct point){scaled[2], scaled[3]}, YELLOW); + vga_print((struct point){55, 80}, YELLOW, + "MOVE JOYSTICK AROUND ITS FULL RANGE"); + vga_print((struct point){43, 113}, YELLOW, + "THEN CENTER JOYSTICK AND PRESS BUTTON A"); + vga_pixel((struct point){VGA_PWIDTH / 2, VGA_PHEIGHT / 2}, BLACK); + } while (!joy.button[0]); + for (int i = 0; i < 4; i++) + joystick_config.center[i] = joy.axis[i]; + vga_clear(LIGHT_BLUE); + do + joystick_read(&joy); + while (joy.button[0]); +} diff --git a/official/Flag 计算机/src/get_flag_system/keyboard.h b/official/Flag 计算机/src/get_flag_system/keyboard.h new file mode 100644 index 0000000..a90b598 --- /dev/null +++ b/official/Flag 计算机/src/get_flag_system/keyboard.h @@ -0,0 +1,33 @@ +#include "int.h" + +static bool kbhit() +{ + bool result; + asm volatile ("mov $1, %%ah\n" + "int $0x16\n" + "jnz set%=\n" + "mov $0, %0\n" + "jmp done%=\n" + "set%=:\n" + "mov $1, %0\n" + "done%=:\n" + : "=rm"(result)); + return result; +} + +static uint16_t kb_read() +{ + uint16_t key; + asm volatile ("mov $1, %%ah\n" + "int $0x16\n" + "jnz get%=\n" + "mov $0, %%ax\n" + "jmp done%=\n" + "get%=:\n" + "mov $0, %%ah\n" + "int $0x16\n" + "jmp done%=\n" + "done%=:\n" + : "=a"(key)); + return key; +} diff --git a/official/Flag 计算机/src/get_flag_system/math.h b/official/Flag 计算机/src/get_flag_system/math.h new file mode 100644 index 0000000..be61f4a --- /dev/null +++ b/official/Flag 计算机/src/get_flag_system/math.h @@ -0,0 +1,19 @@ +#ifndef MATH_H +#define MATH_H + +static inline int abs(int x) +{ + return x < 0 ? -x : x; +} + +static inline int max(int a, int b) +{ + return a < b ? b : a; +} + +static inline int min(int a, int b) +{ + return b < a ? b : a; +} + +#endif diff --git a/official/Flag 计算机/src/get_flag_system/numbers b/official/Flag 计算机/src/get_flag_system/numbers new file mode 100644 index 0000000..b02562c --- /dev/null +++ b/official/Flag 计算机/src/get_flag_system/numbers @@ -0,0 +1 @@ +20597,19141,29258,17804,29076,28746,24890,28979,26196,31833,26624,24774,18916,29028,24033,22913,23436,25750,26539,21652,31296,22446,16506,21949,22761,30221,29477,29617,16497,23022,23179,30781,23877,29171,31665,26534,32159,22583,27525,28708,31216,17158,31988,32190,23747,21272,21278,24727,29984,25303,23445,23119,23155,26346,26389,30747,28948,31418,21323,31758,30911,18790,21312,25099,22348,25409,29357,22180,23588,28794,18133,25624,21972,23401,24821,31369,25187,31517,19840,28836,20794,20239,24523,30814,24016,17954,21227,16691,30290,23391,20482,24822,31968,30651,27908,22690,30875,31003,31747,19978,25482,18563,30143,27788,26658,26295,23244,27086,26456,24251,28647,22783,27460,19187,23252,24078,19203,26251,18113,19542,24533,16666,24038,32744,28670,30438,26379,18591,30109,26509,20947,27696,22945,27542,32128,25416,21675,19389,27085,29380,20163,21102,30936,30862,18230,21904,16938,16579,20641,27551,22740,24666,16836,23306,27661,26506,28623,29816,20166,29405,23982,30046,19365,24926,19029,32448,17567,17156,18678,28594,19769,28631,25769,31309,24457,30625,21825,29811,17112,31370,25345,24333,24005,31606,30942,21441,30599,22894,18015,19994,27901,26868,21948,27614,23449,21289,19588,19955,28133,16696,31509,26219,19946,27895,28760,28547,28315,16614,26006,17129,24769,24608,17714,17682,18532,17597,29247,28789,27011,29841,32640,17508,27662,23548,29514, \ No newline at end of file diff --git a/official/Flag 计算机/src/get_flag_system/only_dos.exe b/official/Flag 计算机/src/get_flag_system/only_dos.exe new file mode 100644 index 0000000..f29e9ce Binary files /dev/null and b/official/Flag 计算机/src/get_flag_system/only_dos.exe differ diff --git a/official/Flag 计算机/src/get_flag_system/port.h b/official/Flag 计算机/src/get_flag_system/port.h new file mode 100644 index 0000000..32bcc90 --- /dev/null +++ b/official/Flag 计算机/src/get_flag_system/port.h @@ -0,0 +1,22 @@ +#ifndef PORT_H +#define PORT_H + +#include "int.h" + +static inline int16_t inportb(int16_t port) +{ + volatile uint8_t value; + asm volatile ("in %%dx, %%ax\n" + : "=a"(value) + : "d"(port)); + return value; +} + +static inline void outportb(int16_t port, uint8_t value) +{ + asm volatile ("out %%al, %%dx\n" + : /* no output */ + : "d"(port), "a"(value)); +} + +#endif diff --git a/official/Flag 计算机/src/get_flag_system/print.h b/official/Flag 计算机/src/get_flag_system/print.h new file mode 100644 index 0000000..ab9938b --- /dev/null +++ b/official/Flag 计算机/src/get_flag_system/print.h @@ -0,0 +1,21 @@ +static void print(char *string) +{ + asm volatile ("mov $0x09, %%ah\n" + "int $0x21\n" + : /* no output */ + : "d"(string) + : "ah"); +} + +static void printl(unsigned long n) +{ + volatile char buffer[12]; + int i = sizeof(buffer); + buffer[--i] = '$'; + if (n == 0) + buffer[--i] = '0'; + else + for (; n > 0; n /= 10) + buffer[--i] = '0' + (n % 10); + print((char *) buffer + i); +} diff --git a/official/Flag 计算机/src/get_flag_system/rand.h b/official/Flag 计算机/src/get_flag_system/rand.h new file mode 100644 index 0000000..64a730f --- /dev/null +++ b/official/Flag 计算机/src/get_flag_system/rand.h @@ -0,0 +1,21 @@ +#ifndef RANDOM_H +#define RANDOM_H + +#include "int.h" + +#define RAND_MAX 4294967295 + +static uint32_t rand_seed = 375226057; + +static uint32_t rand(void) +{ + rand_seed = rand_seed * 1103515245 + 12345; + return rand_seed; +} + +static uint32_t randn(uint32_t n) +{ + return (rand() >> 7) % n; +} + +#endif diff --git a/official/Flag 计算机/src/get_flag_system/speaker.h b/official/Flag 计算机/src/get_flag_system/speaker.h new file mode 100644 index 0000000..4b9cb75 --- /dev/null +++ b/official/Flag 计算机/src/get_flag_system/speaker.h @@ -0,0 +1,229 @@ +#pragma once + +#include "int.h" +#include "tone.h" + +struct note { + unsigned frequency; + uint16_t length; +}; + +struct sample { + int priority; + size_t length; + struct note notes[]; +}; + +struct sample fx_menu_toggle = { + .priority = 50, + .length = 3, + { + {600, 2}, + {1000, 1}, + {700, 2} + } +}; + +struct sample fx_menu_select = { + .priority = 55, + .length = 4, + { + {800, 2}, + {900, 3}, + {1000, 4}, + {0, 10} + } +}; + +struct sample fx_intro_music = { + .priority = 100, + .length = 11, + { + {262, 10}, + {247, 10}, + {220, 10}, + {196, 10}, + {247, 10}, + {220, 10}, + {196, 10}, + {247, 10}, + {220, 10}, + {0, 10}, + {110, 20}, + } +}; + +struct sample fx_end_music = { + .priority = 200, + .length = 15, + { + {62, 50}, + {0, 2}, + {62, 50}, + {0, 2}, + {62, 50}, + {0, 2}, + {73, 25}, + {0, 2}, + {65, 20}, + {0, 2}, + {62, 50}, + {0, 2}, + {55, 50}, + {0, 2}, + {62, 100}, + } +}; + +struct sample fx_explode = { + .priority = 10, + .length = 11, + { + {62, 1}, + {47, 1}, + {20, 1}, + {96, 1}, + {47, 1}, + {20, 1}, + {96, 1}, + {47, 1}, + {20, 1}, + {89, 1}, + {60, 1}, + } +}; + +struct sample fx_fire0 = { + .priority = 0, + .length = 4, + { + {200, 1}, + {190, 1}, + {180, 1}, + {170, 1} + } +}; + +struct sample fx_fire1 = { + .priority = -10, + .length = 5, + { + {150, 1}, + {120, 1}, + {100, 1}, + {120, 1}, + {135, 1} + } +}; + +struct sample fx_fire2 = { + .priority = -5, + .length = 5, + { + {300, 1}, + {320, 1}, + {330, 1}, + {335, 1}, + {340, 1} + } +}; + +struct sample fx_fire3 = { + .priority = 1, + .length = 14, + { + {50, 7}, + {75, 7}, + {100, 7}, + {150, 7}, + {200, 1}, + {250, 1}, + {300, 1}, + {370, 1}, + {360, 1}, + {350, 1}, + {340, 1}, + {330, 1}, + {320, 1}, + {310, 1} + } +}; + +struct sample fx_hit = { + .priority = 5, + .length = 5, + { + {120, 3}, + {130, 3}, + {140, 3}, + {150, 3}, + {160, 3} + } +}; + +struct sample fx_powerup = { + .priority = 50, + .length = 2, + { + {800, 3}, + {900, 3} + } +}; + +struct sample fx_boss = { + .priority = 500, + .length = 13, + { + {110, 15}, + {0, 2}, + {110, 15}, + {0, 2}, + {110, 5}, + {175, 30}, + {0, 2}, + {175, 15}, + {0, 2}, + {175, 15}, + {0, 2}, + {175, 5}, + {110, 30}, + } +}; + +struct speaker { + struct sample *sample; + int index, step; +}; + +void speaker_play(struct speaker *speaker, struct sample *sample) +{ + if (!speaker->sample || speaker->sample->priority < sample->priority) { + speaker->sample = sample; + speaker->index = -1; + speaker->step = 0; + } +} + +void speaker_step(struct speaker *speaker) +{ + if (speaker->sample) { + if (speaker->step) { + speaker->step--; + } else { + speaker->index++; + if (speaker->index >= speaker->sample->length) { + speaker->sample = 0; + tone_off(); + } else { + struct note note = speaker->sample->notes[speaker->index]; + if (note.frequency == 0) + tone_off(); + else { + tone(note.frequency); + tone_on(); + } + speaker->step = note.length; + } + } + } +} diff --git a/official/Flag 计算机/src/get_flag_system/time.h b/official/Flag 计算机/src/get_flag_system/time.h new file mode 100644 index 0000000..3028d96 --- /dev/null +++ b/official/Flag 计算机/src/get_flag_system/time.h @@ -0,0 +1,54 @@ +#ifndef TIME_H +#define TIME_H + +static uint32_t get_tick() +{ + unsigned long result; + asm volatile ("push %%es\n" + "mov $0,%%bx\n" + "mov %%bx,%%es\n" + "mov $0x046C,%%bx\n" + "mov %%es:(%%bx),%%eax\n" + "pop %%es\n" + : "=a"(result) + : /* no inputs */ + : "bx"); + return result; +} + +static uint32_t get_time() +{ + uint16_t high, low; + asm volatile ("mov $0x2C, %%ah\n" + "int $0x21\n" + : "=c"(high), "=d"(low) + : + : "ah"); + return (((uint32_t) high) << 16) | low; +} + +/* Granularity of 976 usec and doesn't work in DOSBox. */ +static void usleep(uint32_t us) +{ + asm volatile ("mov $0x86, %%ah\n" + "int $0x15\n" + : /* no outputs */ + : "c"(us >> 16), "d"(us & 0x16) + : "ah", "flags"); +} + +/* Granularity of 55 msec. */ +static void msleep(int ms) +{ + uint32_t count = ms / 54; // 18.2 Hz + uint32_t last = get_tick(); + while (count) { + uint32_t now = get_tick(); + if (now != last) { + last = now; + count--; + } + } +} + +#endif diff --git a/official/Flag 计算机/src/get_flag_system/tone.h b/official/Flag 计算机/src/get_flag_system/tone.h new file mode 100644 index 0000000..375d251 --- /dev/null +++ b/official/Flag 计算机/src/get_flag_system/tone.h @@ -0,0 +1,18 @@ +#include "port.h" + +static void tone_on() +{ + outportb(0x61, inportb(0x61) | 0x03); +} + +static void tone_off() +{ + outportb(0x61, inportb(0x61) & ~0x03); +} + +static void tone(unsigned frequency) +{ + uint16_t period = 1193180 / frequency; + outportb(0x42, period & 0xff); + outportb(0x42, period >> 8); +} diff --git a/official/Flag 计算机/src/get_flag_system/vga.h b/official/Flag 计算机/src/get_flag_system/vga.h new file mode 100644 index 0000000..129b1a5 --- /dev/null +++ b/official/Flag 计算机/src/get_flag_system/vga.h @@ -0,0 +1,117 @@ +#ifndef VGA_H +#define VGA_H + +#include "math.h" + +#define VGA_PWIDTH 320 +#define VGA_PHEIGHT 200 + +enum VGA_COLOR { + BLACK, BLUE, GREEN, CYAN, RED, MAGENTA, BROWN, LIGHT_GRAY, DARK_GRAY, + LIGHT_BLUE, LIGHT_GREEN, LIGHT_CYAN, LIGHT_RED, LIGHT_MAGENTA, + YELLOW, WHITE +}; + +struct point { + short x, y; +}; + +struct rect { + struct point tl, br; +}; + +/* Switch to VGA mode 13 and set ES. */ +static void vga_on() +{ + asm volatile ("mov $0x0013, %%ax\n" + "int $0x10\n" + "mov $0xA000, %%ax\n" + "mov %%ax, %%es\n" + : /* no outputs */ + : /* no inputs */ + : "ax"); +} + +static void vga_off() +{ + asm volatile ("mov $0x0003, %%ax\n" + "int $0x10\n" + "mov $0xA000, %%dx\n" + "mov %%dx, %%es\n" + : /* no outputs */ + : /* no inputs */ + : "ax", "dx"); +} + +static void vga_pixel(volatile struct point p, uint8_t color) +{ + if (p.x >= 0 && p.x < VGA_PWIDTH && p.y >= 0 && p.y < VGA_PHEIGHT) + asm volatile ("imul $320, %%bx\n" + "add %%ax, %%bx\n" + "mov %%cl, %%es:(%%bx)\n" + : /* no outputs */ + : "a"(p.x), "b"(p.y), "c"(color) + : "dx"); +} + +static void vga_clear(char color) +{ + asm volatile ("mov %%al, %%ah\n" + "mov $0, %%di\n" + "push %%ax\n" + "shl $16, %%eax\n" + "pop %%ax\n" + "mov $16000, %%cx\n" + "rep\n" + "stosl\n" + : /* no outputs */ + : "a"(color) + : "cx", "di"); +} + +static void vga_line(struct point a, struct point b, uint8_t color) +{ + int dx = abs(b.x - a.x), sx = a.x < b.x ? 1 : -1; + int dy = abs(b.y - a.y), sy = a.y < b.y ? 1 : -1; + int err = (dx > dy ? dx : -dy) / 2, e2; + for(;;) { + vga_pixel(a, color); + if (a.x == b.x && a.y == b.y) + break; + e2 = err; + if (e2 > -dx) { + err -= dy; + a.x += sx; + } + if (e2 < dy) { + err += dx; + a.y += sy; + } + } +} + +static void vga_rect(struct rect r, uint8_t color) +{ + vga_line(r.tl, (struct point){r.br.x, r.tl.y}, color); + vga_line(r.tl, (struct point){r.tl.x, r.br.y}, color); + vga_line(r.br, (struct point){r.br.x, r.tl.y}, color); + vga_line(r.br, (struct point){r.tl.x, r.br.y}, color); +} + +static void vga_vsync() +{ + asm volatile ("mov $0x03DA, %%dx\n" + "current%=:" + "in %%dx, %%al\n" + "and $0x8, %%al\n" + "jnz current%=\n" + "restart%=:" + "in %%dx, %%al\n" + "and $0x8, %%al\n" + "jz restart%=\n" + : /* no outputs */ + : /* no inputs */ + : "al", "dx"); +} + +#endif diff --git a/official/Flag 计算机/src/get_flag_system/vga_font.h b/official/Flag 计算机/src/get_flag_system/vga_font.h new file mode 100644 index 0000000..0adf71e --- /dev/null +++ b/official/Flag 计算机/src/get_flag_system/vga_font.h @@ -0,0 +1,32 @@ +#include "int.h" +#include "vga.h" + +/* Letters are 7 pixels tall and 5 pixels wide. */ + +/* http://redd.it/2ba3g3 */ +static const char LINES[] = "BCDEIKOPQRSTUVYZ\\_`"; +static const char LETTERS[] = + "DFJSJJJRJJRJJRGJIIIJGRJJJJJRSIIRIISSIIRIIIHIILJJHJJJSJJJGDDDD" + "DGAAAAAJHJKMOMKJIIIIIISJQNJJJJJJPNLJJGJJJJJGRJJRIIIGJJJNGCRJJ" + "RMKJGJIGAJGSDDDDDDJJJJJJGJJJJJFDJJJNQJJJJFDFJJJJFDDDDSABDEIS"; + +static int vga_font_line(int c, int row) { + return c == ' ' ? 0 : LINES[LETTERS[(c - 'A') * 7 + row] - 'A'] - 'A'; +} + +static void vga_print(struct point p, uint8_t color, const char *message) +{ + for (int y = 0; y < 7; y++) { + for (int x = 0; message[x]; x++) { + int c = message[x]; + int line = vga_font_line(c, y); + for (int i = 0; i < 5; i++) { + if ((line >> i) & 0x01) { + int dx = p.x + x * 6 + (4 - i); + int dy = p.y + y; + vga_pixel((struct point){dx, dy}, color); + } + } + } + } +}