0%

正文

hosts是将一个域名解析到ip地址的一个关联“数据库”

通过手动修改hosts,我们可以将域名解析到自己想要的ip上去

路径

对于win10系统

C:\Windows\System32\drivers\etc

该文件目录下找到hosts文件,以管理员身份打开

(否则无法修改)

修改格式

在hosts文件末尾添加信息,每行一条

[ip] [host]

e.g. 127.0.0.1 www.myhost.com

Snipaste_2019-06-13_20-52-44.png

如何在Linux上搭建Minecraft服务器

搭建minecraft服务器并不复杂,只需要一些linux的基础操作知识就行了

灵感来自csdn,教程为自己编写.

购买服务器

我选择的是阿里云学生机,这样的配置能带好几个人加上几个大mod,几个小伙伴一起玩已经足够了

理论上Ubuntu也可以使用,不过这个教程里面的指令都是基于centOS的

Snipaste_2019-06-09_11-39-45.png

配置服务器

查看java版本

java --version

如果提示

[[email protected] /]# java –version
-bash: java: command not found

则说明没有安装java

安装java

sudo yum install java-1.8.0-openjdk

选择目录

然后自己找一个想装mc的目录

cd usr
mkdir minecraft
cd minecraft

获取mc服务器端

根据你玩的mc的版本,可以下载相应的jar包

sudo wget https://s3.amazonaws.com/Minecraft.Download/versions/版本号/minecraft_server.版本号.jar

以我的为例,目前支持mod的最新版本是1.12.2

sudo wget https://s3.amazonaws.com/Minecraft.Download/versions/1.12.2/minecraft_server.1.12.2.jar

开启游戏!

创建启动脚本

在这之前,先创建一个启动脚本,方便后续一键启动

sudo vi start.sh

在start.sh填入如下的内容

sudo java -Xms120m -Xmx160m -jar /usr/minecraft/minecraft_server.1.12.2.jar nogui

其中120m,160m分别是给服务器分配的内存,建议如果是开forege服的话把最大内存调高一点,不然mod带不动


开启

开启服务器

bash start.sh

不要着急,这里一定启动不了的,因为你没有同意用户协议

[04:00:32] [Server thread/INFO]: You need to agree to the EULA in order to run the server. Go to eula.txt for more info.

打开eula.txt

sudo vi eula.txt

把false改为true

eula=true

安装forge

现在已经可以启动服务器了,无mod需求的可以直接开服,无需进行下面的步骤

但是我们还是无法运行mod,需要安装forge

可以去官网自行下载,也可以用我的指令

sudo wget https://files.minecraftforge.net/maven/net/minecraftforge/forge/1.12.2-14.23.5.2768/forge-1.12.2-14.23.5.2768-installer.jar

接下来是安装forge

java -jar forge-1.12.2-14.23.5.2768-installer.jar nogui --installServer

Extracting: /forge-1.12.2-14.23.5.2768-universal.jar
To: /usr/minecraft/./forge-1.12.2-14.23.5.2768-universal.jar
The server installed successfully, you should now be able to run the file forge-1.12.2-14.23.5.2768-universal.jar
You can delete this installer file now if you wish

这个 forge-1.12.2-14.23.5.2768-universal.jar 就是启动forge服务器的启动端

打开start.sh把原版启动程序换为forge的启动程序

sudo vi start.sh

填入

sudo java -Xms120m -Xmx160m -jar /usr/minecraft/forge-1.12.2-14.23.5.2768-universal.jar nogui

开服

bash start.sh

[04:22:29] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing start region for level 0
[04:22:30] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 2%
[04:22:32] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 4%
[04:22:33] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 7%
[04:22:49] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 50%
[04:22:50] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 52%
[04:22:55] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 64%
[04:23:05] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 97%
[04:23:06] [Server thread/INFO] [minecraft/DedicatedServer]: Done (39.625s)! For help, type “help” or “?”

其他补充

screen

开服之后的服务器其实并不稳定,只要你关闭远程连接,mc便会自动结束

为了解决这个问题 就要用到screen工具

sudo yum install screen

在开服之前,先创建一个screen

screen -S mc

创建好screen之后再开启mc服务器

当然,如果需要切换出来 , 按一下Ctrl+a 再按一下d即可

[[email protected] ~]# screen -S mc
[detached from 7293.mc]
[[email protected] ~]#

下次还需进入该screen,就不需要创建了,直接

screen -r mc

mod

要加载mod,将服务器端使用的mod放入/usr/minecraft/mods文件夹,重启mc服务器即可

server.properties

配置文件修改,具体请参照官方文档

通常是把pvp,正版检测关闭

还可以限制总加入人数,服务器难度,以及最大高度等等

Java Edition
Key Type Default Value Description
allow-flight boolean false Allows users to use flight on your server while in Survival mode, if they have a modthat provides flight installed.With allow-flight enabled, griefers will possibly be more common, because it will make their work easier. In Creative mode this has no effect.false - Flight is not allowed (players in air for at least 5 seconds will be kicked).true - Flight is allowed, and used if the player has a fly mod installed.
allow-nether boolean true Allows players to travel to the Nether.false - Nether portals will not work.true - The server will allow portals to send players to the Nether.
difficulty string easy Defines the difficulty (such as damage dealt by mobs and the way hunger and poison affects players) of the server.If a legacy difficulty number is specified it will be silently converted to a difficulty name.peaceful (0)easy (1)normal (2)hard (3)
enable-command-block boolean false Enables command blocks
enable-query boolean false Enables GameSpy4 protocol server listener. Used to get information about server.
enable-rcon boolean false Enables remote access to the server console.
force-gamemode boolean false Force players to join in the default game mode.false - Players will join in the gamemode they left in.true - Players will always join in the default gamemode.
gamemode string survival Defines the mode of gameplay.If a legacy gamemode number is specified it will be silently converted to a gamemode name.survival (0)creative (1)adventure (2)spectator (3)
generate-structures boolean true Defines whether structures (such as villages) will be generated.false - Structures will not be generated in new chunks.true - Structures will be generated in new chunks.Note: Dungeons will still generate if this is set to false.
generator-settings string blank The settings used to customize world generation. See Superflat and Customized for possible settings and examples.
hardcore boolean false If set to true, server difficulty is ignored and set to hard and players will be set to spectator mode if they die.
level-name string world The “level-name” value will be used as the world name and its folder name. You may also copy your saved game folder here, and change the name to the same as that folder’s to load it instead.Characters such as ‘ (apostrophe) may need to be escaped by adding a backslash before them.
level-seed string blank Add a seed for your world, as in Singleplayer.Some examples are: minecraft, 404, 1a2b3c.
level-type string default Determines the type of map that is generated.default - Standard world with hills, valleys, water, etc.flat - A flat world with no features, can be modified with generator-settings.largebiomes - Same as default but all biomes are larger.amplified - Same as default but world-generation height limit is increased.buffet - Same as default unless generator-settings is set to a preset.
max-build-height integer 256 The maximum height in which building is allowed. Terrain may still naturally generate above a low height limit.
max-players integer (0-2147483647) 20 The maximum number of players that can play on the server at the same time. Note that if more players are on the server it will use more resources. Note also, op player connections are not supposed to count against the max players, but ops currently cannot join a full server. However, this can be changed by going to the file called ops.json in your server directory, opening it, finding the op you want the change, and changing the setting called bypassesPlayerLimit to true (the default is false). This means that that op will not have to wait for a player to leave in order to join. Extremely large values for this field result in the client-side user list being broken.
max-tick-time integer (0–(2^63 - 1)) 60000 The maximum number of milliseconds a single tick may take before the server watchdog stops the server with the message, A single server tick took 60.00 seconds (should be max 0.05); Considering it to be crashed, server will forcibly shutdown. Once this criterion is met, it calls System.exit(1).-1 - disable watchdog entirely (this disable option was added in 14w32a)
max-world-size integer (1-29999984) 29999984 This sets the maximum possible size in blocks, expressed as a radius, that the world border can obtain. Setting the world border bigger causes the commands to complete successfully but the actual border will not move past this block limit. Setting the max-world-size higher than the default doesn’t appear to do anything.Examples:Setting max-world-size to 1000 will allow you to have a 2000x2000 world border.Setting max-world-size to 4000 will give you an 8000 x 8000 world border.
motd string A Minecraft Server This is the message that is displayed in the server list of the client, below the name.The MOTD supports color and formatting codes.The MOTD supports special characters, such as “♥”. However, such characters must be converted to escaped Unicode form. An online converter can be found here.If the MOTD is over 59 characters, the server list will likely report a communication error.
network-compression-threshold integer 256 By default it allows packets that are n-1 bytes big to go normally, but a packet that nbytes or more will be compressed down. So, lower number means more compression but compressing small amounts of bytes might actually end up with a larger result than what went in.-1 - disable compression entirely0 - compress everythingNote: The Ethernet spec requires that packets less than 64 bytes become padded to 64 bytes. Thus, setting a value lower than 64 may not be beneficial. It is also not recommended to exceed the MTU, typically 1500 bytes.
online-mode boolean true Server checks connecting players against Minecraft account database. Only set this to false if your server is not connected to the Internet. Hackers with fake accounts can connect if this is set to false! If minecraft.net is down or inaccessible, no players will be able to connect if this is set to true. Setting this variable to off purposely is called “cracking” a server, and servers that are presently with online mode off are called “cracked” servers, allowing players with unlicensed copies of Minecraft to join.true - Enabled. The server will assume it has an Internet connection and check every connecting player.false - Disabled. The server will not attempt to check connecting players.
op-permission-level integer (1-4) 4 Sets the default permission level for ops when using /op. All levels inherit abilities and commands from levels before them.1 - Ops can bypass spawn protection.2 - Ops can use all singleplayer cheats commands (except /publish, as it is not on servers; along with /debug and /reload) and use command blocks. Command blocks, along with Realms owners/operators, have the same permissions as this level.3 - Ops can use most multiplayer-exclusive commands, including /debug, /reload, and commands that manage players (/ban, /op, etc).4 - Ops can use all commands including /stop, /save-all, /save-on, /save-off, /forceload add, and /forceload remove.
player-idle-timeout integer 0 If non-zero, players are kicked from the server if they are idle for more than that many minutes.Note: Idle time is reset when the server receives one of the following packets:Click WindowEnchant ItemUpdate SignPlayer DiggingPlayer Block PlacementHeld Item ChangeAnimation (swing arm)Entity ActionClient StatusChat MessageUse Entity
prevent-proxy-connections boolean false If the ISP/AS sent from the server is different from the one from Mojang’s authentication server, the player is kickedtrue - Enabled. Server prevents users from using vpns or proxies.false - Disabled. The server doesn’t prevent users from using vpns or proxies.
pvp boolean true Enable PvP on the server. Players shooting themselves with arrows will only receive damage if PvP is enabled.true - Players will be able to kill each other.false - Players cannot kill other players (also known as Player versus Environment (PvE)).Note: Indirect damage sources spawned by players (such as lava, fire, TNT and to some extent water, sand and gravel) will still deal damage to other players.
query.port integer (1-65534) 25565 Sets the port for the query server (see enable-query).
rcon.password string blank Sets the password to rcon.
rcon.port integer (1-65534) 25575 Sets the port to rcon.
resource-pack string blank Optional URI to a resource pack. The player may choose to use it.Note that the “:” and “=” characters need to be escaped with backslash (), e.g. http://somedomain.com/somepack.zip?someparam=somevalueNote download success/failure is logged by the client, not by the server.
resource-pack-sha1 string blank Optional SHA-1 digest of the resource pack, in lowercase hexadecimal. It’s recommended to specify this. This is not yet used to verify the integrity of the resource pack, but improves the effectiveness and reliability of caching.
server-ip string blank Set this if you want the server to bind to a particular IP. It is strongly recommended that you leave server-ip blank!Set to blank, or the IP you want your server to run (listen) on.
server-port integer (1-65534) 25565 Changes the port the server is hosting (listening) on. This port must be forwarded if the server is hosted in a network using NAT (If you have a home router/firewall).
snooper-enabled boolean true Sets whether the server sends snoop data regularly to http://snoop.minecraft.net.false - disable snooping.true - enable snooping.
spawn-animals boolean true Determines if animals will be able to spawn.true - Animals spawn as normal.false - Animals will immediately vanish.Tip: if you have major lag, turn this off/set to false.
spawn-monsters boolean true Determines if monsters will be spawned.true - Enabled. Monsters will appear at night and in the dark.false - Disabled. No monsters.This setting has no effect if difficulty = 0 (peaceful). If difficulty is not = 0, a monster can still spawn from a Monster Spawner.Tip: if you have major lag, turn this off/set to false.
spawn-npcs boolean true Determines whether villagers will be spawned.true - Enabled. Villagers will spawn.false - Disabled. No villagers.
spawn-protection integer 16 Determines the radius of the spawn protection as 2x+1. Setting this to 0 will not disable spawn protection. 0 will protect the single block at the spawn point. 1 will protect a 3x3 area centered on the spawn point. 2 will protect 5x5, 3 will protect 7x7, etc. This option is not generated on the first server start and appears when the first player joins. If there are no ops set on the server, the spawn protection will be disabled automatically.
use-native-transport boolean true Linux server performance improvements: optimized packet sending/receiving on Linuxtrue - Enabled. Enable Linux packet sending/receiving optimizationfalse - Disabled. Disable Linux packet sending/receiving optimization
view-distance integer (2-32) 10 Sets the amount of world data the server sends the client, measured in chunks in each direction of the player (radius, not diameter). It determines the server-side viewing distance. (see Render distance)10 is the default/recommended. If you have major lag, reduce this value.*Note: *A value less than 9 will have big impacts on the mobs’ spawn of your server as it mentionned by the bug MC-2536.
white-list boolean false Enables a whitelist on the server.With a whitelist enabled, users not on the whitelist will be unable to connect. Intended for private servers, such as those for real-life friends or strangers carefully selected via an application process, for example.false - No white list is used.true - The file whitelist.json is used to generate the white list.Note: Ops are automatically white listed, and there is no need to add them to the whitelist.
enforce-whitelist boolean false Enforces the whitelist on the server.When this option is enabled, users who are not present on the whitelist (if it’s enabled) will be kicked from the server after the server reloads the whitelist file.false - No user will be kicked if not on the whitelist.true - Online users not on the whitelist will be kicked.

In versions prior to Java Edition 1.12, the announce-player-achievements boolean property (default true) was used to toggle whether achievementswere broadcasted to all players. This property no longer exists, but if it is set, the announceAdvancements gamerule will automatically be updated to match and the property will be removed.

TranslucentTB

win10的界面可谓比win7、xp高到不知道哪里去了,然而事物总是有两面性,win10任务栏一直是我们所诟病的一个东西

A lightweight utility that makes the Windows taskbar translucent/transparent.

TranslucentTB

效果

半透明

Snipaste_2019-06-08_00-32-03.png

全透明

Snipaste_2019-06-08_00-31-36.png

Features

看起来现在加了不少功能

主要的还是改变任务栏透明度

  • Advanced color picker supporting alpha and live preview to change the taskbar’s color.

  • Taskbar states

    (choose one - color can be customized on every state except Normal):

    • Blur: Will make the taskbar slightly blurred. 半透明
    • Clear: Transparent taskbar. 全透明
    • Normal: Regular Windows style. (as if TranslucentTB was not running)
    • Opaque: No transparency.
    • Fluent: Windows 10 April 2018 update and up only. Will give the taskbar an appearance similar to Microsoft’s Fluent Design guidelines.
  • Dynamic

    modes (these can be used together and each of them provides a taskbar state and color you can customize):

    • Dynamic Windows: Will change the taskbar to a different appearance if a window is currently maximised.
    • Dynamic Start Menu: Will change the taskbar appearance when the start menu is opened.
    • Dynamic Cortana: Will change the taskbar appearance when Cortana (or the search menu if Cortana is disabled) is open.
    • Dynamic Timeline/Task View: Will change the taskbar apperance when the Timeline (or Task View on older builds) is open.
  • Ability to show or hide the Aero Peek button. Can be customized at will or dynamic.

下载

  1. Microsoft Store (最近添加的)
  2. the releases tab(zip压缩包)

用途

如果你正在写word的实验报告,而苦于word的代码显示错位,那你就来对地方了!

工具

  1. 打开这个网页PlanetB;
  2. 谷歌搜索syntax highlight code in word documents,检索结果的第一个

步骤

​ 打开网页,把需要的代码粘贴进去,然后show highlighted即可

JustRe

JustRe.7z

思路

程序读入了26位 十六进制数

其中前8为送入eax寄存器

把eax扩展为了16个字节 01234567012345670123456701234567 记作 input

后两位(假设为ab) 填充为了ababababababababab…..ababab,记作 ab

从内存中取16个字节,记作 key1

还从内存取了16个字节,形如00000003000000020000000100000000 记作 key2

key = (ab + key1)^ (input + key2) 并且将结果存在原来key1的位置

依次循环

注意key2第二次 key2’ += key2 ,而不是直接从内存取

接下来的循环 循环了八次,是对从0x405058的32个字节进行处理,每次四个字节

同样

input 01 23 45 67

key 从内存中取四个字节

ab 用89位填充的四个字节

esi 从0x10 开始 一直到0x18

key = (ab + key) ^ (input + esi) 并且将结果存在key的位置

然后 0x405018 和 0x404148的 0x60个字节进行比较,要相等

事实证明,后面这些运算,对于解出input的帮助并不大,我们只需要解出一组input,并且判断它们是否是四个分块都相等即可

dec1 = 0x4364162A031410D2EF95C26D80B899BD
enc1 = 0x405004A100000278EC81F0E483EC8B55
key1 = 0x00000003000000020000000100000000


def FILL(a): #用八九位这一个字节去填充为16字节
return a * 0x01010101010101010101010101010101

def DIVIDE(a):
for i in range(4):
res.append((a << (32 * i) & 0xffffffffffffffffffffffffffffffff) >> (32 * 3))
return res

def ADD(a, b):
a = DIVIDE(a)
b = DIVIDE(b)
res = 0
for i in range(4):
res += ((a[i]+b[i]) & 0xffffffff) << (32 * (3-i))
return res

def CALC(dec,enc,key,t):
return (ADD(FILL(t),dec) ^ enc) - key


for t in range(100):#枚举第八第九位的所有情况
res = CALC(dec1,enc1,key1,t)
if(inpu & 0xffffffff == res >> (3 * 32)):
print(hex(CALC(dec1,enc1,key1,t) >> (3*32)),hex(t))

前十位 1324229810

用来过验证的passwd:13242298100123456789abcdef

后面这个加密函数是好像藏在data区里面的,看起来应该是一个加密算法,谷歌了几个比较关键的常数,发现是个3des加密

https://www.cnblogs.com/one--way/archive/2016/07/05/5643771.html

密钥应该是这个 AFSAFCEDYCXCXACNDFKDCQXC

再配上解密后的密文(实际上只用到了16个字节,剩下的8个字节可要可不要)

注意:大端序,不能直接复制,要先把顺序颠倒一下

轮子不太完整,修改了一下,以下是main函数中修改过的内容

	char k[32] = "AFSAFCEDYCXCXACNDFKDCQXC";

char data[128] = {
0x50,0x7C,0xA9,0xE6,
0x87,0x09,0xCE,0xFA,
0x20,0xD5,0x0D,0xCF,
0x90,0xBB,0x97,0x6C,0
}; /* 原始明文 */
nlen = strlen(data);


.....

for (i = 0; i < len; i += 8) {
DES_ecb3_encrypt((const_DES_cblock *)(src + i), (DES_cblock *)(out + i), &ks1, &ks2, &ks3, DES_DECRYPT);
}

printf("encrypted Hex:");
for (i = 0; i < len; i++) {
printf("%02X" , *(out + i));
}
printf("\n");

printf("encrypted Bin:");
for (i = 0; i < len; i++) {
printf("%c", *(out + i));
}
printf("\n");

Rctf_babyre2

rctf_babyre2

思路

alarm

程序一开头就有一个alarm函数,这会使我们在调试的时候中途退出,直接把call alarm nop掉即可

sub_55761565891A

__int64 __fastcall sub_55761565891A(void *a1)
{
unsigned int v2; // [rsp+10h] [rbp-10h]
signed int v3; // [rsp+14h] [rbp-Ch]

v2 = 0;
print_notice();
memset(a1, 0, 0x100uLL);
read(0, a1, 0xFFuLL);
v3 = strlen((const char *)a1);
if ( v3 <= 16 )
{
if ( v3 > 7 )
v2 = 1;
else
print_notice();
}
else
{
print_notice();
}
return v2;
}

sub_5576156589CC

__int64 __fastcall sub_5576156589CC(void *a1)
{
unsigned int v2; // [rsp+1Ch] [rbp-14h]
signed int i; // [rsp+20h] [rbp-10h]
signed int v4; // [rsp+24h] [rbp-Ch]

v2 = 0;
print_notice();
memset(a1, 0, 0x100uLL);
read(0, a1, 0xFFuLL);
v4 = strlen((const char *)a1);
if ( v4 <= 16 )
{
if ( v4 > 7 )
{
v2 = 1;
for ( i = 0; i < v4; ++i )
{
if ( *((_BYTE *)a1 + i) <= 9 || *((_BYTE *)a1 + i) > 99 )
{
print_notice();
return 0;
}
}
}
else
{
print_notice();
}
}
else
{
print_notice();
}
return v2;
}

简单的读入账户和密码,不赘述

不赘述就出问题了

读密码的时候你没发现一个奇怪的事情吗?

if ( *((_BYTE *)a1 + i) <= 9 || *((_BYTE *)a1 + i) > 99 )

密码可以不是可见字符

sub_557615658ACE

char *__fastcall sub_557615658ACE(__int64 a1, __int64 a2)
{
__int64 v2; // rdx
int i; // [rsp+10h] [rbp-40h]
__int64 v5; // [rsp+14h] [rbp-3Ch]
__int64 dest; // [rsp+20h] [rbp-30h]
__int64 v7; // [rsp+28h] [rbp-28h]
char v8; // [rsp+30h] [rbp-20h]
char v9; // [rsp+31h] [rbp-1Fh]
char v10; // [rsp+32h] [rbp-1Eh]
char v11; // [rsp+33h] [rbp-1Dh]
char v12; // [rsp+34h] [rbp-1Ch]
char v13; // [rsp+35h] [rbp-1Bh]
char v14; // [rsp+36h] [rbp-1Ah]
char v15; // [rsp+37h] [rbp-19h]
char v16; // [rsp+38h] [rbp-18h]
char v17; // [rsp+39h] [rbp-17h]
char v18; // [rsp+3Ah] [rbp-16h]
char v19; // [rsp+3Bh] [rbp-15h]
char v20; // [rsp+3Ch] [rbp-14h]
char v21; // [rsp+3Dh] [rbp-13h]
char v22; // [rsp+3Eh] [rbp-12h]
char v23; // [rsp+3Fh] [rbp-11h]
char v24; // [rsp+40h] [rbp-10h]
unsigned __int64 v25; // [rsp+48h] [rbp-8h]

v25 = __readfsqword(0x28u);
v8 = -8;
v9 = -44;
v10 = -43;
v11 = -36;
v12 = -55;
v13 = -38;
v14 = -49;
v15 = -50;
v16 = -41;
v17 = -38;
v18 = -49;
v19 = -46;
v20 = -44;
v21 = -43;
v22 = -56;
v23 = -102;
v24 = -79;
dest = 0LL;
v7 = 0LL;
v5 = (unsigned int)strlen((const char *)a1);
if ( (signed int)v5 <= 16 )
{
memcpy(&dest, (const void *)a1, (signed int)v5);// 复制内存
for ( i = 0; 16 - (signed int)v5 > i; ++i )
*((_BYTE *)&dest + i + (signed int)v5) = i + 1;// 对于没有满16位的account 自动补全16位(补全一个从0开始的递增序列)
}
else
{
v2 = *(_QWORD *)(a1 + 8);
dest = *(_QWORD *)a1;
v7 = v2;
}
return sub_55761565981E(&v8, 17, (__int64)&dest, 16, (int *)a2);
}
char *__fastcall sub_55761565981E(const void *buf, int a2, __int64 a1, int a4, int *a5)
{
int *v6; // [rsp+0h] [rbp-40h]
__int64 acc; // [rsp+8h] [rbp-38h]
signed int v8; // [rsp+24h] [rbp-1Ch]
int v9; // [rsp+28h] [rbp-18h]
char *dest; // [rsp+30h] [rbp-10h]

acc = a1;
v6 = a5;
dest = 0LL;
v8 = 0;
if ( buf )
{
if ( a2 > 0 )
{
if ( a1 )
{
if ( a4 == 16 )
{
if ( a5 )
{
*a5 = 0;
v9 = 4 * (a2 / 4 + 1);
dest = (char *)malloc(v9 + 1);
if ( dest )
{
memcpy(dest, buf, a2);
memset(&dest[a2], 4 - a2 % 4, 4 - a2 % 4);// 填充了3
dest[v9] = 0;
xtea((unsigned int *)dest, v9 / 4, acc);// 这里是执行了加密的过程,account作为密钥
*v6 = v9;
v8 = 1;
}
}
}
}
}
}
if ( !v8 )
{
if ( dest )
{
free(dest);
dest = 0LL;
}
if ( v6 )
*v6 = 0;
}
return dest;
}

简单来说就是利用xtea算法,将buf(上面的数组)加密了,密钥是账户名

sub_557615658C02

__int64 __fastcall sub_557615658C02(__int64 a1)
{
signed int v2; // [rsp+14h] [rbp-81Ch]
int v3; // [rsp+18h] [rbp-818h]
unsigned int v4; // [rsp+18h] [rbp-818h]
int i; // [rsp+1Ch] [rbp-814h]
char buf[2048]; // [rsp+20h] [rbp-810h]
char v7; // [rsp+820h] [rbp-10h]
unsigned __int64 v8; // [rsp+828h] [rbp-8h]

v8 = __readfsqword(0x28u);
memset(buf, 0, sizeof(buf));
v7 = 0;
print_notice();
read(0, buf, 0x400uLL);
v3 = strlen(buf);
if ( v3 & 1 || v3 > 1024 ) // 长度不超过1024,且必须为偶数
{
v4 = 0;
print_notice();
}
else
{
v2 = 1;
for ( i = 0; i < v3; ++i ) // 检测输入是否合规
{
if ( (buf[i] <= 47 || buf[i] > 57) && (buf[i] <= 96 || buf[i] > 102) && (buf[i] <= 64 || buf[i] > 70) )// 只准输入数字,大小写的字母a~f
{
print_notice();
v2 = 0;
break;
}
}
if ( v2 ) // 如果输入合规
v4 = sub_5576156587C6(buf, v3, (_QWORD *)a1);
else
v4 = 0;
}
return v4;
}

读入了偶数个字节的数据,并且长度不超过1024,数据只能在09 af A~F的范围

sub_557615658DD6

_BYTE *__fastcall sub_557615658DD6(const char *passwd, __int64 data, int chunk, _DWORD *a4)
{
_DWORD *v5; // [rsp+0h] [rbp-50h]
int v6; // [rsp+Ch] [rbp-44h]
signed int v7; // [rsp+2Ch] [rbp-24h]
signed int v8; // [rsp+30h] [rbp-20h]
int i; // [rsp+34h] [rbp-1Ch]
int v10; // [rsp+38h] [rbp-18h]
int v11; // [rsp+3Ch] [rbp-14h]
_BYTE *ptr; // [rsp+40h] [rbp-10h]

v6 = chunk;
v5 = a4;
v7 = 0;
ptr = 0LL;
if ( data )
{
if ( chunk > 0 )
{
if ( passwd )
{
v10 = strlen(passwd);
if ( v10 > 0 )
{
ptr = malloc(v10 + 1);
if ( ptr )
{
ptr[v10] = 0;
v8 = 1;
for ( i = 0; i < v10; ++i )
{
v11 = passwd[i] - (passwd[i] % 10 + passwd[i] / 10);// 由passwd生成了一个偏移地址
if ( v11 >= v6 )
{
v8 = 0;
break;
}
ptr[i] = *(_BYTE *)(v11 + data); // ptr[i]就等于这个偏移地址上面的数据
}
if ( v8 ) // 若正常退出
{
*v5 = v10;
v7 = 1;
}
}
}
}
}
}
if ( !v7 && ptr )
{
free(ptr);
ptr = 0LL;
}
return ptr;
}

用passwd可以算出来一个偏移,对应着data中的数据,生成了一个ptr数组

sub_557615658FB0

for ( j = 0; j < passwd_len; ++j )
*((_BYTE *)&dest + j) ^= 0xCCu; // ptr进行异或0xcc
::ptr = sub_5576156599B9(v6, v7, (__int64)&dest, 16, &dword_55761585B058);

sub_5576156599B9:

xtea((unsigned int *)dest, buf_len / -4, v7);// 这里执行解密的过程,解密encrypted,密钥为ptr_xor

公式

xtea(xtea(buf, accout, ENCRYPT) ,f(data,passwd) , DECRYPT)

f(data, passwd) == accout

passwd到data是一个很简单的映射,映射完之后要异或一个0xcc,异或结果应该刚好等于account

solve

script from dalao

https://balsn.tw/ctf_writeup/20190518-rctf2019/#babyre2

我自己还没用过pwntools。。。没想到要直接给程序传入非可见字符,所以就借用了一下国外大佬的脚本

from pwn import *

r=remote("139.180.215.222", 20000)
print r.recvuntil("account")
r.send("a"*16)
print r.recvuntil("password")
r.send("\x10"*16)
r.recvuntil("data")
r.send("010203040506070809ad0b0c0d0e0f") #ad=61^cc
r.shutdown("send")

r.interactive()

RCTF_babyre1

rctf_babyre1

思路

以下是与输入相关的指令

main

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
unsigned __int64 *in; // rdx
int v4; // ecx
unsigned int v5; // eax
unsigned __int64 v6; // rdx
int v7; // eax
int *v8; // rax
char *v9; // rbx
__int64 i; // rax
int v12; // [rsp+4h] [rbp-124h]
void *ptr; // [rsp+8h] [rbp-120h]
unsigned __int64 str; // [rsp+10h] [rbp-118h]
unsigned __int64 v15; // [rsp+118h] [rbp-10h]

v15 = __readfsqword(0x28u);
setbuf(stdin, 0LL);
setbuf(stdout, 0LL);
setbuf(stderr, 0LL);
ptr = 0LL;
v12 = 0;
memset(&str, 0, 0x100uLL);
__printf_chk(1LL, "Input right flag you can got 'Bingo!' :");
__isoc99_scanf("%31s", &str); // 输入为16位
in = &str;
do
{
v4 = *(_DWORD *)in;
in = (unsigned __int64 *)((char *)in + 4);
v5 = ~v4 & (v4 - 0x1010101) & 0x80808080;
}
while ( !v5 );
if ( !((unsigned __int16)~(_WORD)v4 & (unsigned __int16)(v4 - 0x101) & 0x8080) )
v5 >>= 16;
if ( !((unsigned __int16)~(_WORD)v4 & (unsigned __int16)(v4 - 0x101) & 0x8080) )
in = (unsigned __int64 *)((char *)in + 2);
v6 = (char *)in - __CFADD__((_BYTE)v5, (_BYTE)v5) - 3 - (char *)&str;
if ( v6 > 0x10 )
{
puts("input is too long!");
}
else if ( v6 == 16 )
{
v7 = change_into_number((unsigned __int64)&str, 16, &ptr);// 这个程序就是把输入的内容(十六进制)转换成了程序可读的数字
if ( v7
&& (v8 = xtea_keychanged(ptr, v7, (__int64)&unk_55883B7B0010, 16, &v12), (v9 = (char *)v8) != 0LL)
&& v12 > 0
&& (unsigned __int16)crc16((__int64)v8, v12) == 0x69E2 )
{
for ( i = 0LL; v12 > (signed int)i; ++i )
v9[i] ^= 0x17u;
puts(v9);
if ( ptr )
free(ptr);
free(v9);
}
else
{
puts("input flag is wrong!");
}
}
else
{
puts("input is too short!");
}
return 0LL;
}

可以看到输入后的字符串进行了一大堆看不懂的操作,但是能推测出来输入的长度为16位

用ida调试可知,change_into_number这个函数把输入的字符串进行了转换

完成了16进制字符串 -> 16进制整数的过程

xtea_keychanged中的一个子函数

signed __int64 __fastcall sub_55883B5AECE0(int *a1, signed int a2, __int64 a3)
{
__int64 v3; // rbp
signed int v4; // ebx
unsigned int v5; // ecx
int v6; // er12
int *v7; // r13
unsigned int v8; // er14
unsigned int v9; // ecx
unsigned int v10; // er15
unsigned int v11; // ebx
unsigned int v12; // er10
int *v13; // r9
int v14; // er8
unsigned int v15; // esi
int v16; // eax
unsigned __int8 v17; // dl
unsigned int v18; // eax
int *v19; // r10
unsigned int v20; // eax
char v21; // dl
unsigned int v22; // eax
signed __int64 result; // rax
int v24; // esi
unsigned int v25; // er11
int *v26; // r13
int v27; // er14
unsigned int v28; // er12
unsigned int v29; // ebx
int *v30; // r8
int v31; // esi
unsigned int v32; // er9
unsigned int v33; // er10
unsigned int v34; // eax
int v35; // ecx
unsigned __int8 v36; // dl
unsigned int v37; // eax
int v38; // er15
int *v39; // r8
unsigned int v40; // er10
int v41; // eax
bool v42; // zf
signed int v43; // [rsp+0h] [rbp-40h]
int *v44; // [rsp+0h] [rbp-40h]
unsigned int v45; // [rsp+Ch] [rbp-34h]

v3 = a3;
v4 = a2;
v5 = *a1;
v43 = a2;
if ( a2 > 1 )
{
v6 = a2 - 1;
v7 = &a1[a2 - 1];
v8 = 0;
v9 = *v7;
v10 = ((a2 - 4) & 0xFFFFFFFE) + 2;
v45 = 0x9E3779B9 * (52 / a2) - 0x4AB325AA;
do
{
v8 -= 0x61C88647;
v11 = v8 >> 2;
if ( v43 <= 3 )
{
v14 = 0;
}
else
{
v12 = *a1;
v13 = a1;
v14 = 0;
do
{
v15 = v13[1];
v13 += 2;
v16 = (v9 ^ *(_DWORD *)(v3 + 4LL * (((unsigned __int8)v14 ^ (unsigned __int8)v11) & 3))) + (v15 ^ v8);
v17 = v14 + 1;
v14 += 2;
v18 = v12 + ((((v9 >> 5) ^ 4 * v15) + ((v15 >> 3) ^ 16 * v9)) ^ v16);
v12 = *v13;
*(v13 - 2) = v18;
v9 = v15
+ (((4 * v12 ^ (v18 >> 5)) + (16 * v18 ^ (v12 >> 3))) ^ ((v12 ^ v8)
+ (v18 ^ *(_DWORD *)(v3
+ 4LL
* (((unsigned __int8)v11 ^ v17) & 3)))));
*(v13 - 1) = v9;
}
while ( v10 != v14 );
}
v19 = &a1[v14];
do
{
v20 = v19[1];
v21 = v11 ^ v14++;
++v19;
v22 = *(v19 - 1)
+ (((v9 ^ *(_DWORD *)(v3 + 4LL * (v21 & 3))) + (v20 ^ v8)) ^ ((16 * v9 ^ (v20 >> 3)) + ((v9 >> 5) ^ 4 * v20)));
*(v19 - 1) = v22;
v9 = v22;
}
while ( v6 > v14 );
v9 = *v7
+ (((v22 ^ *(_DWORD *)(v3 + 4LL * (((unsigned __int8)v6 ^ (unsigned __int8)v11) & 3))) + (*a1 ^ v8)) ^ ((4 * *a1 ^ (v22 >> 5)) + (16 * v22 ^ ((unsigned int)*a1 >> 3))));
*v7 = v9;
}
while ( v8 != v45 );
return 0LL;
}
result = 1LL;
if ( a2 < -1 )
{
v24 = -a2;
v25 = -1640531527 * (52 / v24 + 6);
if ( v25 )
{
v26 = &a1[v24 - 1];
v27 = ~v4;
v44 = &a1[~v4];
v28 = ~v4 - 2 - ((~v4 - 3) & 0xFFFFFFFE);
do
{
v29 = v25 >> 2;
if ( v27 <= 2 )
{
v31 = v27;
}
else
{
v30 = v44;
v31 = v27;
v32 = *v44;
do
{
v33 = *(v30 - 1);
v30 -= 2;
v34 = v32;
v32 = *v30;
v35 = ((v5 ^ v25) + (v33 ^ *(_DWORD *)(v3 + 4LL * (((unsigned __int8)v31 ^ (unsigned __int8)v29) & 3)))) ^ ((4 * v5 ^ (v33 >> 5)) + ((v5 >> 3) ^ 16 * v33));
v36 = v31 - 1;
v31 -= 2;
v37 = v34 - v35;
v38 = *v30;
v30[2] = v37;
v5 = v33
- (((16 * v38 ^ (v37 >> 3)) + ((v32 >> 5) ^ 4 * v37)) ^ ((v32 ^ *(_DWORD *)(v3
+ 4LL
* (((unsigned __int8)v29 ^ v36) & 3)))
+ (v25 ^ v37)));
v30[1] = v5;
}
while ( v28 != v31 );
}
v39 = &a1[v31];
do
{
v40 = *(v39 - 1);
--v39;
v5 = v39[1]
- (((v5 ^ v25) + (v40 ^ *(_DWORD *)(v3 + 4LL * (((unsigned __int8)v29 ^ (unsigned __int8)v31) & 3)))) ^ (((v5 >> 3) ^ 16 * v40) + ((v40 >> 5) ^ 4 * v5)));
v39[1] = v5;
--v31;
}
while ( v31 );
v41 = *a1
- (((((unsigned int)*v26 >> 5) ^ 4 * v5) + (16 * *v26 ^ (v5 >> 3))) ^ ((*(_DWORD *)(v3 + 4LL * (v29 & 3)) ^ *v26)
+ (v25 ^ v5)));
v42 = v25 == -1640531527;
v25 += 1640531527;
v5 = v41;
*a1 = v41;
}
while ( !v42 );
}
return 0LL;
}
return result;
}

由0x9E3779B9可知,这是一个xtea加密(解密)算法

然后加解密所使用的常数有所改变,是内存中的16字节的数组

xtea(v8, -(v10 >> 2), constant)

这个 -(v10 >> 2)明显是一个负数,而xtea函数为负时,就是解密的过程

在调试时xtea_keychanged这个函数执行完后就直接报wrong

经高人指点,这个是xtea解密失败,程序判断这个密码解不出来,就直接报错了

xtea_keychanged

int *__fastcall xtea_keychanged(void *src, int const_8, __int64 a3, int a4, int *a5)
{
int *v5; // rbp
int v6; // er12
__int64 constant; // r14
int *string; // rbx
int *v9; // rax
int v10; // esi
signed int v11; // eax
int v13; // er12

v5 = a5;
if ( !src || (v6 = const_8, const_8 <= 0) || (constant = a3) == 0 || a4 != 16 )
{
if ( !a5 )
goto LABEL_14;
goto LABEL_13;
}
string = 0LL;
if ( a5 )
{
*a5 = 0;
if ( !(const_8 & 3) )
{
v9 = (int *)malloc(const_8 + 1);
string = v9;
if ( v9 )
{
memcpy(v9, src, const_8); // v9 存储了输入的16进制数
v10 = const_8 + 3;
if ( v6 >= 0 )
v10 = v6;
xtea(string, -(v10 >> 2), constant); // xtea对输入的字符串进行解密
v11 = *((unsigned __int8 *)string + v6 - 1);// 取第八个字符
*((_BYTE *)string + v6) = 0;
*v5 = v6;
if ( v6 > v11 && v11 <= 4 )
{
v13 = v6 - v11; // 8 - v11
*v5 = v13;
*((_BYTE *)string + v13) = 0; // 把某一位置零了
return string;
}
free(string);
}
}
LABEL_13:
*v5 = 0;
LABEL_14:
string = 0LL;
}
return string;
}
*((_BYTE *)string + v13) = 0;         // 把某一位置零了

这句话很关键,把某一位截断了,而这一位只能是倒数第二位

crc16

__int64 __fastcall sub_55883B5AF3D0(__int64 a1, int a2)
{
__int64 v2; // r12
__int64 v3; // rbp
__int16 v4; // ax
__int16 v5; // ax
__int16 v6; // dx
__int16 v7; // ax
__int16 v8; // dx
__int16 v9; // ax
__int16 v10; // dx
__int16 v11; // ax
unsigned __int8 v13; // [rsp+5h] [rbp-23h]
unsigned __int16 v14; // [rsp+6h] [rbp-22h]
unsigned __int64 v15; // [rsp+8h] [rbp-20h]

v15 = __readfsqword(0x28u);
v13 = 0;
v14 = 0;
if ( a2 )
{
v2 = a1;
v3 = a1 + (unsigned int)(a2 - 1) + 1;
do
{
while ( 1 )
{
v13 = *(_BYTE *)(++v2 - 1);
sub_55883B5AF270(&v13, &v13);
v4 = v14 ^ (v13 << 8);
if ( ((v14 ^ (v13 << 8)) & 0x8000u) != 0 )
v5 = 2 * v4 ^ 0x1021;
else
v5 = 2 * v4;
v6 = 2 * v5 ^ 0x1021;
if ( v5 >= 0 )
v6 = 2 * v5;
v7 = 2 * v6 ^ 0x1021;
if ( v6 >= 0 )
v7 = 2 * v6;
v8 = 2 * v7 ^ 0x1021;
if ( v7 >= 0 )
v8 = 2 * v7;
v9 = 2 * v8 ^ 0x1021;
if ( v8 >= 0 )
v9 = 2 * v8;
v10 = 2 * v9 ^ 0x1021;
if ( v9 >= 0 )
v10 = 2 * v9;
v11 = 2 * v10 ^ 0x1021;
if ( v10 >= 0 )
v11 = 2 * v10;
if ( v11 < 0 )
break;
v14 = 2 * v11;
if ( v2 == v3 )
goto LABEL_19;
}
v14 = 2 * v11 ^ 0x1021;
}
while ( v2 != v3 );
}
LABEL_19:
sub_55883B5AF2D0(&v14, &v14);
return v14;
}

也是通过0x1021可知,这是一个crc16校验,校验码为0x1021

if ( v2 == v3 )
goto LABEL_19;

由这句话可知,v2会从起始字节一直遍历到v3处,那么a2就要构造得刚好把这些值覆盖,可知a2=6,所以解密后的那个数组的最后一个字节就是2

调试tips:

有效的加密字符串 4290cd6dc6ae54cc

解密后得0123456789abcd02

大致思路

  1. 程序读入16位的十六进制数,并转化为8字节
  2. 将数据进行xtea解密

同时这个自带加密函数,只需要把输入的参数取反,就是逆过程了

  1. 将解密后的数据进行crc16校验(校验码为0x1021),得到结果0x69E2
  2. 这个解密后的数组去异或0x17能得到”Bingo!” 字符串

solve

def crc16(data: bytes, poly=0x1021):
'''
CRC-16-CCITT Algorithm
'''
data = bytearray(data)
crc = 0xFFFF
for b in data:
cur_byte = 0xFF & b
for _ in range(0, 8):
if (crc & 0x0001) ^ (cur_byte & 0x0001):
crc = (crc >> 1) ^ poly
else:
crc >>= 1
cur_byte >>= 1
crc = (~crc & 0xFFFF)
crc = (crc << 8) | ((crc >> 8) & 0xFF)

return crc & 0xFFFF


enc = "Bingo!"
dec = []

for i in enc:
dec.append(hex(ord(i) ^ 0x17))
dec.append(hex(6))
dec.append(hex(2))

print(dec)

557e797078360602

然后再拿这个字符串去加密一遍,就得到flag了

rctf{2a2e71aab6168fb6}

[11] Accepting connection from 192.168.133.1...
Input right flag you can got 'Bingo!' :2a2e71aab6168fb6

Bingo!

后续:据说倒数第二字节是个padding

有空再填坑 https://blog.csdn.net/shift_wwx/article/details/84256774

CCSP2019

有幸通过了CCF CSP 认证,获得了参加CCSP西南赛区比赛的资格

来到川大(江安校区)

这个校区管理非常严格,进门之前甚至需要出示身份证和准考证( x

校园中一片宁静,可能是因为星期六的原因,并没有太多人愿意在这个搭好的天气出来走动走动,偶尔看见一两对情侣唧唧我我,酸死我了

MVIMG_20190518_165030.jpg

人文气息极其浓厚

MVIMG_20190518_162435.jpg

这个比赛并不是很出名,整个教学楼就只看到两个指示牌,这是其中一个(

MVIMG_20190518_080614.jpg

CCSP分区赛是第一次在川大举办的,看出来主办方对于应急事件的处理方法还不够了解,试机过程中状况百出

8:30上机调试,没有提供windows的IDE,仅仅有一个linux虚拟机,配上里面“丰富”的IDE,不过我并不觉得这是一个好办法,因为川大的电脑实在是太垃圾了。。虚拟机真的是带不动啊

幸好我带了U盘,装上了Dev-Cpp

经过无数次重启,好不容易进去了比赛界面

OJ是清华大学提供的,这个非常好

MVIMG_20190518_092009.jpg

比赛期间还算进行得很顺利,不过嘛,菜是原罪

第一题是图论题,并不是什么高大上的题目,题目叙述非常简单,就是靠自己爆搜,剪枝吧

第二题模拟题,模拟raid5阵列恢复数据的过程

第三题是一道看不懂的与c++的类有关的题目,,,但是题目给的样例程序,交上去居然有分

中午12:30有午餐,是德克士的汉堡跟鸡腿,主办方在给选手提供良好比赛环境上还是下了很大功夫的

图片:颁奖现场

MVIMG_20190518_153959.jpg

水了个铜奖

奖励是罗技鼠标一个

IMG_20190518_233712.jpg

总结:这次川大之行非常愉快,一方面是见了见老同学聊了聊往事,另一方面我看到了川大在准备比赛上的用心和负责,虽然自己的水平还不够继续参加总决赛,不过这次区域赛无疑是一个很好的锻炼,期待以后的表现