加了限定条件的Helloworld

今年水群的时候无意中发现CNSS的招新题目,关于加了限定条件的Helloworld的写法。

*1.不用 “ ” 输出Helloworld。

*2.不用 ; 输出Helloworld。

*3.不用 # 输出Helloworld。

*4.不用各种括号输出Helloworld。

HelloWorld

不用 “ ” 输出Helloworld

第一种比较简单,直接把“HelloWorld”写成ascii码用字符输出,代码如下:

1
2
3
4
5
6
#include <stdio.h>
int main()
{
char HelloWorld[] = {72,101,108,108,111,87,111,114,108,100,33};
puts(HelloWorld);
}

运行结果:

不用 ; 输出Helloworld

第二种,用if来规避’;’,代码如下:

1
2
3
4
int main()
{
if (puts("Helloworld")){}
}

运行结果:

不用 # 输出Helloworld

我自行声明了printf函数:

1
2
3
4
5
6
extern int printf (const char* format, ...);
int main()
{
printf("HelloWorld!\n");
return 0;
}

运行结果:

不用各种括号输出Helloworld

这第四问算超纲了吧,shellcode。

一个文件的起始不是main函数,而是_start函数

在一个elf文件中,托入ida分析,可以看到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.text:08048310                 public _start
.text:08048310 _start proc near
.text:08048310 xor ebp, ebp
.text:08048312 pop esi
.text:08048313 mov ecx, esp
.text:08048315 and esp, 0FFFFFFF0h
.text:08048318 push eax
.text:08048319 push esp
.text:0804831A push edx
.text:0804831B push offset __libc_csu_fini
.text:08048320 push offset __libc_csu_init
.text:08048325 push ecx
.text:08048326 push esi
.text:08048327 push offset main
.text:0804832C call ___libc_start_main
.text:08048331 hlt
.text:08048331 _start endp

.text:08048327处,将main作为参数入栈,然后执行,即跳转到main函数的位置,执行main中的语句。所以,我们可以直接在main中构造数据,当main函数被执行时该段数据被直接执行。

也就是说,如果我们有如下代码:

1
const char main[]="\x00\x01\x02\x03";

当执行 ___libc_start_main 后跳到main变量上时,就会执行“\x00\x01\x02\x03”,若是将汇编转为这个形式,则会执行这些汇编语句。

但是题目中并不允许我们用[]。在GCC中,相邻的的变量,在储存空间中位置也是相邻的,所以我们可以把数据分开存储:

1
const char main=0x1, main1=0x1, main2=0x2, main3=0x3;

这样可以达到同样的效果,并且符合题意。

因此,只要把输出部分转换成汇编形式,然后再写成机械码,就可以实现题目。本篇blog在此不做详细说明,所以,请学会如何写shellcode

致谢

Plusls’ blog

后记

本来最后一问没想写这么多。当时找不到题目描述,然后在CNSS 2017里面问了一下,狗头大大:看我Blog啊。

然后看狗头大大分析了一波,感觉自己多写点吧。

致谢Plusls。

文章目录
  1. 1. HelloWorld
    1. 1.1. 不用 “ ” 输出Helloworld
    2. 1.2. 不用 ; 输出Helloworld
    3. 1.3. 不用 # 输出Helloworld
    4. 1.4. 不用各种括号输出Helloworld
  2. 2. 致谢
    1. 2.1. 后记
,