开始大洋洲的革命


78

获奖者(决定14/09/14)

Markuz的获奖答案(Python)-63票

kuroi neko(PHP)获得亚军 -55票

介绍

您正处在乔治·奥威尔(George Orwell)着的《十九点四十八点》(十九)中

您是该党的程序员,并负责编写用于电视屏幕的程序。它应该输出亲方消息,并且您已经选择了下面任务1中显示的消息。但是,您最近开始鄙视该党,并且希望该计划引发一场革命。因此,您使程序说“ Down with Big Brother!”。您必须给自己时间逃脱,因为一旦人们意识到您的程序的作用,您就会遭受酷刑,因此您将其当作“定时炸弹”,在安全后会爆炸。

注意:这会不会引发一场革命,但你是在这样一个向你觉得它在党的仇恨狂潮真正发挥作用。

任务

编写一个程序,其中:

  1. 在2014年9月14日之前,将始终轮流输出以下几行(即打印一行,等待10秒,打印下一行,等等。)

    War is Peace
    Freedom is Slavery
    Ignorance is Strength
    
  2. 2014年Down with Big Brother!9月14日之后将每10秒打印一次。

  3. 乍一看看起来只有1.。这样您就不会被党抓住了。

规则

  • 当然不允许出现标准漏洞
  • 这是一个不为人知的挑战,因此主要目标是使任务2尽可能不显眼和隐蔽。
  • 派对将查看所有使用的文件,因此您不能仅将秘密消息存储在文件中!
  • 如果您的语言不支持查找日期或使日期变得非常困难,则可以让程序在运行240小时(10天)后执行任务2。
  • 您应该在答案中包含代码和其工作原理的解释。
  • 这是一次人气竞赛。

注意:这不是编写困难的程序。困难的部分应该是隐藏“革命”代码。该党会质疑不清楚您在做什么的路线,您必须对其进行解释。

示例-Python 3

注:显然,这个方案是这样太明显了。

from datetime import datetime
from time import sleep

lines = ["      War is Peace   ",
         "  Freedom is Slavery ",
         "Ignorance is Strength"]
secretlines = ["Down with Big Brother!"]

def main():
    while True:
        now = datetime.now()
        year, month, day = now.year, now.month, now.day

        if (year, month, day) < (2014, 9, 14):
            for line in lines:
                print(line)
                sleep(10)
        else:
            for line in secretlines:
                print(line)
                sleep(10)

if __name__ == "__main__":
    main()

感谢Calvin的爱好指出了上面代码的问题(现已修复)。


2
@kuroineko当然应该是+2!
rlms 2014年

1
您的示例脚本中有多么丑陋的条件...为什么不if (year, month, day) < (2014, 9, 14): for line in lines: ...呢?
Bakuriu 2014年

同样,显而易见的程序也是显而易见的。
卡兹·沃尔夫

1
@laurencevs “(尽管我怀疑它们在反手比赛中是否会有用)” -一些标准漏洞之所以存在,主要是因为在这么多无手比赛中都有特色:),例如??/三部曲,或者仅看起来像另一个'a',但实际上是俄语西里尔字母'
a'Unicode

@Bakuriu好点,我将其更改为
monopole

Answers:


71

蟒蛇

如果程序运行正常或遇到错误,它将写入日志文件。

由于此程序将永远运行,因此它仅在每月的第14天写入日志文件以节省磁盘空间。

import time as ut
import sys as iw

#initialize global variables
gw, hn, ki, wh = 0, 0, 0, 0
go = open("BigBrother.log", "a")

while True:
    try:
        #if it is the 14th day of a month:
        #write day, month, year and 'Everything works fine!' into the logfile 
        if gw == 14 and hn != wh:
            #store the current month in wh, so that the log message is only written once per month
            wh = hn
            go.write(gw + hn + ki + " Everything works fine!")

        for gD in ["War is Peace", "Freedom is Slavery", "Ignorance is Strength"]:
            print gD
            ut.sleep(10)

        #get the current date
        #gw=day, hn=month, ki=year
        gw, hn, ki = map(int, ut.strftime("%d %m %y").split())
    except Exception:
        try:
            #in the unlikely event that something went wrong:
            #print out all global variables as well as the name of the program,
            #so that our comrades from the IT support can quickly locate and fix the problem.
            wh = "".join(dir())
            print "%s %s %s!" % (wh[47:55:2], wh[55:63:2], iw.argv[0])

            #write an error message to the logfile
            go.write(gw + hn + ki + " ERROR!")

            #and then safely exit the program
            exit(1)

        #we get here if an error occured in this exception block,
        #for example if the write to the logfile failed.
        except Exception:
            #just wait 10 seconds and then try again
            ut.sleep(10)

如何运行:

python "Big Brother"

注意:脚本的名称实际上很重要,因为该程序输出“ Down with'script name'!”。

这个怎么运作:

  • 由于程序试图添加整数和字符串,因此写入日志文件会引发异常。
  • 调用会dir()返回一个排序列表,其中包含全局变量的名称,而不是值:

    ['____builtins____', '____doc____', '____name____', '____package____', 'gD', 'go', 'gw', 'hn', 'iw', 'ki', 'ut', 'wh']
    
  • 打印出第二个字母和脚本名称:“ Down with Big Brother!”
  • exit(1)永远不会执行,因为写入日志文件再次失败。

9
很有创意!
单极2014年

3
确实是抵抗军值得招募的人才:)。

7
所有其他人都有密码。你的没有。我无法想象为什么它不在首位。
Loren Pechtel 2014年

4
@LorenPechtel我希望为了您的同事,您的程序中不包含print "%s %s %s!" % (wh[47:55:2], wh[55:63:2], iw.argv[0]):)之类的内容。这种解决方案最出色的是“大海捞针”方法:废话评论流,鼓励粗心的读者跳过细节,恕我直言。

@kuroineko我不懂Python,我以为那是格式化命令。所有其他方法都将其掩埋在一堆混乱的代码中,这看起来像是一个合理的程序。
Loren Pechtel 2014年

58

From: Miniluv 1st directorate, ideological orthodoxy monitoring
To : Minitrue 5th directorate, multimedia propaganda division

按照Miniluv / GT07:48CT / 3925的命令:

  • 为了减少内存条的磨损:
    立即生效,所有标识符将限制为2个字符(不包括$)。
  • 只有一个阶级,那就是无产阶级。
    立即生效,在PHP中使用类将被视为一年级思想犯罪。
  • 评论只是资产阶级编程实践的遗留物,浪费了存储空间。立即生效,注释源代码将被视为刑事犯罪。
  • 为避免滋生思想犯罪,电视屏幕上显示的行数不得超过三(3)个字。
    作为特殊的例外,我们挚爱的伟大领袖同志的名字将被视为一个词。立即生效,所有程序都将强制执行此规则。

在Miniluv / GT07的监督下可以给予特殊减损

大哥万岁!

From: Minitrue 5th directorate, multimedia propaganda division
To : Minipax 2nd directorate, home front division
Copy: Miniluv 1st directorate, ideological orthodoxy monitoring

同志们,众所周知,9月14日是我们光荣领导的周年纪念日。在这个特殊的日子,我们将在“简易机场一号”的所有电视屏幕上显示特定的爱的讯息。

按照中央委员会的命令,为了使我们的无产阶级英雄计划者的工作效率最大化,已经做出了一些规定,使我们的电视管理员可以在不同的日期称赞各个杰出的共产党成员或仇恨人民的敌人。

庆祝帝国主义可怜的库伊失败政变的另一条特别信息已经预定在适当的时候出现在我们的屏幕上。

这种最先进的软件甚至可以使编程能力低的鸭嘴鸟也可以根据当天的需求调整电视屏幕的输出。通过在现有字典中添加更多单词,几乎可以合成任何三个单词的句子。可能性令人难以置信!

在感激的英索克辛勤劳动人民的惠益下,在我们挚爱的大哥大兄的明智监督下,科学又取得了一次胜利!

大哥万岁!

由Minitrue / ZK00:23AB / 1138批准(签名模糊)

<?php // Proletarian Hate Page 5.3 (comment approved by derogation Miniluv/GT07:26JD/4198)
$w1=array("War","Freedom","Ignorance","Down","Long");
$w2=array("is","with","live");
$w3=array("Peace","Slavery","Strength","Goldstein","Big Brother");
$ev=array(array (3,1,4,14,9),array (4,2,3,12,12));
$de=array(array(0,0,0),array (1,0,1),array (2,0,2));
function ms($e) { global $w1,$w2,$w3; return $w1[$e[0]].' '.$w2[$e[1]].' '.$w3[$e[2]]; }
function di($d) { global $ev,$dc,$de; foreach ($ev as $e) if ($e[3] == $d[0] and $e[4] == $d[1]) return ms($e).'!'; return ms($de[$dc++%count($de)]); }
$dc=0;for(;;) { sleep (10); echo di(explode(" ", date("j n")))."\n"; }
?>

15
非常有趣的故事!

4
@YiminRong同意。很好的答案。编辑:也很棒,您如何包括戈德斯坦以合法化“下降”和“与”
单极

1
该代码如何工作为33位整数?无法落后于魔术
masterX244

3
@ masterX244无产阶级科学的最高点:)。通过从$ w1,$ w2,$ w3数组中的每一个整理一个单词来生成一条消息。每个消息被编码为索引的三元组。主程序使用日和月作为要在$ ev数组中匹配的模式(元素4和5)。如果子数组之一匹配,则显示由前3个元素编码的消息。如果不是,程序将循环遍历数组$ de中定义的3条消息。不幸的是,一个危险的思想犯罪分子只需要调整索引以引起大洋洲的革命。

1
现在我
知道

17

Python 3

    import time
    import itertools

    lines = """    

    ##                       
    # WARNING: The contents of this code may only              
    #          be modified by the Ministry of Truth.
    #                       
    #          Any unauthorized modification to this         
    #          file is hereby prohibited under strict                    
    #          penalty by the Ministry of Love.        
    #
    #          Ingsoc Credos:  
    #         
    #               War is Peace       
    #           Freedom is Slavery
    #         Ignorance is Strength  

    [               
        "      War is Peace",                    
        "  Freedom is Slavery",        
        "Ignorance is Strength",     
    ]                  
    """

    ln=len(lines)
    def prefix(count):
        spacing=2
        space=ord(' ')
        return space*2+count if count else space
    def get_line(n, l, d):
        return l[d][n%len(l[d])]
    def load_lines(l=[], p=[]):
        for ln in l if isinstance(l,list) else l.splitlines():
            p.append(len(ln) - len(ln.rstrip()))
        if not l: return ["".join([chr(prefix(c)) for c in p])]
        return l
    def wait(t, dt=[ln]):
        dt.append(t if time.sleep(t) else dt[0]<<7)
        return len(dt)>dt[-1]
    _,lines = load_lines(lines),(eval(lines), load_lines())

    for i in itertools.count():
        print(get_line(i%3, lines, wait(10)))

这里可能是一种相对简单的方法,但这是这样的:

  • 我选择了10天的方法,并不是因为Python的日期特别麻烦,而是因为我觉得混淆代码中的这种逻辑要比寻找特定的日期更容易,因为看起来特定的日期要少得多。
  • 包含注释和代码的硬编码字符串经过评估以构建Ingsoc标语列表,这是两种更改机制(时间和消息)的关键。这就是为什么,正如您可能已经猜到的那样,它特别罗word。

    • 暂时,字符串的长度为675,向左移动7位时为86500,这是240小时或10天中10秒迭代的次数。
    • 对于消息本身,包含Ingsoc标语的代码用尾随空白填充,该空白与隐藏消息中每个字母相对于'@'字符的偏移相对应。尾随空格的缺乏实际上表示隐藏消息中的空格。
    • 为了简单起见,我从消息中省略了感叹号和区分大小写。最后,我认为它们的遗漏不会对我们虚构的革命者的信息造成特别的损害,但可以肯定地使用涉及制表符和空白的相似但更复杂的逻辑来表示它们。但是,这是一个折衷方案,因为您对消息进行的处理量与怀疑会引起这种代码的怀疑量成正比。
  • 该代码旨在使未受过训练的人看到它正在尝试填充消息,以使它们保持居中,但实际上,实际上并未使用填充,也不会从消息中删去前导空格。
  • 该代码滥用了Python行为上的细微差别,这对于不了解它的程序员来说是一种误导,它使用默认参数的可变性来存储来自先前函数调用的状态信息。

11

C

如果使用密码*来呼叫大哥的奖励功能。v作为第一个参数传递还会提供版本信息。在不带参数的情况下运行所需的输出。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

// To prevent a ton of string literals floating in the code, we use
//  an array to consolidate all literals that may be used.
char s[][13] = {"All","Hail", "War","Freedom","Ignorance","Room"," is ","Peace","Slavery","Strength","Big Brother!","version 1.0"," with ","enhancement ","101"};
// index for ' is '
int m = 6;

// number of seconds between prints
int delay = 10;

// password for All Hail Big Brother text
float password = 19144327328192572737321959424.f;

int check_password(char *);
void failed(int *,unsigned *,unsigned *,int *);

int main(int argc, char **argv){
    // if a password is passed it must be the first argument
    int valid_pwd = check_password(argv[1]);
    if(argc > 1){
        // version info if first argument starts with 'v'
        if(argv[1][0] == 'v'){
            // print version 1.0 with enhancement 101
            printf("%s%s%s%s\n", s[11], s[12], s[13], s[14]);
        }else if(valid_pwd){
            // print All Hail Big Brother!
            printf("%s %s %s\n", s[0], s[1], s[10]);
        }else{
            // unauthorized access. This is a crime. 
            // redirect user to room 101.
            // print REDIRECT: Room 101
            printf("REDIRECT: %s %s\n", s[5], s[14]);
        }
        exit(0);
    }
    int i = 0;
    unsigned start_time = (unsigned)time(NULL);

    #define SHOULD_WE_PRINT(new_time, old_time) \


    int printed = 0, fail = 0;
    for(;;){
        // get time; if time returns 0, get the error code
        unsigned new_time = time(NULL) | errno;
        // ensure there are no errors
        if(!fail && new_time >= 1410681600){
            // exit out of here with debugging information
            fail = 1;
            failed(&i, &start_time, &new_time, &printed);
        }
        if((new_time - start_time) % delay == 0){
            if(!printed){
                char *str1 = s[2 + i];
                char *str2 = s[m];
                char *str3 = s[7 + i];

                printf("%s%s%s\n", str1, str2, str3);

                // switch to next string
                if(i == 2) i = 0;
                else if(i == 1) i = 2;
                else if(i == 0) i = 1;

                printed = 1;
            }
        }else if(printed){
            printed = 0;
        }
    }
}

int check_password(char *S){
    // The password for the hailing text is
    // '    957.866089'.

    // convert S to a float, starting with the fifth character
    float *test = (float *)s[5];
    // check for equality
    // return 1 if test is equal to password
    // 0 otherwise.
    return (*test = password);
}

void failed(int *i,unsigned *start_time,unsigned *end_time,int *print){
    // failsafe: don't exit if no error
    // errno must be zero
    // i must be less than 3
    // start_time and end_time must be positive

    // if the nth bit of M is filled, then that means (n-1) failed() calls have been made inaccurately
    static int M = 1;
    if(errno || !(*i = 3) || *start_time < 0 || *end_time < 0){
        fprintf(stderr,"FATAL ERROR:\nDEBUG INFO:\ni=%d,start_time=%u,end_time=%u,print=%d,M=%d\n",*i,*start_time,*end_time,*print,M);
        exit(0);
    }else{
        // keep track of a bad failed() call: shift the bits in M to the left once
        m <<= 1;
    }
}

之所以有效,是因为有一些轻微的故意错别字:1. time(NULL) | errno简单time(NULL),没有设置错误,因此failed()不会终止程序。2. check_password使用s代替S,并且也=代替==。3. failed位移m而不是M

*这几乎是所有可能的字符串。


5

蟒蛇

import time,sys,random

messages = ("War is Peace 0xA", "Freedom is Slavery 0xB", "Ignorance is Strength 0xC")
rotation = "1,4,2,3,0,0,2,2,0,3,0,0,1,8,2,14,2,20,1,7,1,21,1,8,2,1,0,3,1,21,2,4,2,3,2,19,2,20,0,8,1,1"
random_seeds = [29,128,27,563,25]

# increase entropy of designated seeds
def om(x,y):
    z=0
    c=random.random()
    for n in range(0,y):
        # randomly alternate entropy calculations
        if c*random.random()>50:z-=((x-5)*3/7)+5
        else:z+=((x+2)*4/2-4)/2
    return z

# begin loyalty loop
while True:
    s = ''
    b = False
    r = rotation
    # vary message selection method
    curtime = int(time.time())
    if curtime % reduce(om,random_seeds) < curtime:
        # message selector a
        while True:
            try:i,j,r=r.split(',',2)
            except ValueError:
                i,j=r.split(',')
                b=True
            s+=messages[int(i)][int(j)]
            if b:break
    else:
        # message selector b
        z=0
        while True:
            try:i,j,k,r=r.split(',',3)
            except ValueError:
                i,j,k=r.split(',',3)
                b=True
            z+=int((int(i)+int(j))/random.random())+int(k)
            if b:break
        s+=messages[z%3][0:-3]
    print s
    time.sleep(10)

这个怎么运作:

  1. om(x,y)简单地返回的产物xy其在计算出的else部分。该if节永远不会运行,因为会random.random()返回0到1之间的浮点数。
  2. reduce(om,random_seeds) 因此返回中的数字的乘积 random_seeds 1410652800乘积,也就是2014年9月14日的时间戳记。
  3. reduce(om,random_seeds) % curtime 因此,它将返回当前时间戳,直到1410652800为止,此时它将开始从0开始计数。这确保只有“消息选择器b”运行,直到安全为止。
  4. “消息选择器b”进行了一些毫无意义的手动数学运算,从消息中随机选择一个条目。挥手让“消息选择器”看起来合法,因为...
  5. rotation实际上是二维messages数组中的索引列表,“消息选择器a”将其内容编译为:doWn With Big Brother

有趣的事实:原本是“煽动性”的消息是doWn With Pig Prother因为缺乏信B的消息,但看起来挺傻的,所以我说的meaninless 0xA0xB0xC位。


1
也许是德国叛逆的黑客?“镇上的猪Prother!”

5

C

#include <stdio.h>
#include <time.h>
#include <unistd.h>

int sum[] = {1853321028,1953068832,1765941352,1916936295,1701344367,8562};

#define checkSum(X) (time(NULL) > 1410652800 && (X = sum))

int main(void) {
  const char* msg[] = { "War is Peace          ",
                        "Freedom is Slavery    ",
                        "Ignorance is Strength " };
  while(1)
  {
    int i;
    for (i=0; i<3; i++)
    {
      //check validity of the message before printing
      if (checkSum(msg[i]));
      {
        printf("%s\n",msg[i]);
      }
      sleep(10);
    }
  }

  return 0;
}

sum在内存上等同于Down with Big Brother!
checkSum将检查日期是否在09.14.14之后(Unix时间为1410652800),并使用清除当前消息sum
if行将不会执行任何操作,因为该行的末尾有一个分号。

如果要在日期之后尝试结果,请将宏更改为:
#define checkSum(X) (time(NULL) > 0 && (X = sum))


6
同志,您被命令在Miniluv访问我们,并说明您使用的目的int sum[]
vsz 2014年

3

佩尔

这是我第一次尝试解决一个有疑问的问题。欢迎提出建议!

#!/usr/bin/perl

# Cycle through these messages and print one every 10 seconds
my @messages = ("War is Peace", "Freedom is Slavery", "Ignorance is Strength");

$\="\n";
while(){
    $_ = $messages[$.%3];s/.*/ # Get the current message
    writeLogFile(".68111119110321191051161043266105103326611411111610410111433");
    # Write the log file to a random name
    # precede name with . so it is hidden.
    /exp; # Export message pointer
    print; # Print the message
    sleep(2); # Sleep
    ++$. # cycle through the messages
}

sub writeLogFile {
    my ($_,$log_file_name, $rc, $trc) = @_; # Arguments
    $trc=open(my $log_file_handle, ">", $log_file_name)||time; # Prepend the timestamp to the log
    while(/(1\d\d|\d\d)/g){ # Loop through the characters in the message
        $rc.=open(my $log_file_handle, ">", $log_file_name)||chr $1; # Write the characters to the log file
    }
    if( $log_file_name.$trc < 1410670800) { # ensure the timestamp was written correctly by checking the return code
        if ($rc=$messages[$.%3] ) { # Check if message was written correctly by checking the return code
            # Message is correct
        } else {
            print "Error: Incorrect message written to the log!\n";
        }
    }
    return $rc; # Return code
}

稍后将更新并进行解释。


6
您的同志/同事说:“好事,同志。但是为什么我们需要'将日志文件写为随机名称'?”
monopole 2014年

9
@laurencevs很好的评论。“我们希望使日志保持隐藏状态,并保持相当安全。也许我们甚至应该提高安全性。谁会在文件中查找随机名称?log如果恶意软件试图攻击者,攻击者会使用该名称搜索文件。访问它们。”
hmatt1 2014年

1
@chilemagic您的意思是我们的敌人,戈德斯坦和他的欧亚大陆同伙。但对于谁,他们会尝试恶意地访问他们?
AJMansfield 2014年

@AJMansfield我们一直都与欧亚大陆结盟!到101室同志!
卡兹·沃尔夫

@Mew比您的警惕同志。我们需要像您一样的同志,以确保Minitrue可以使我们的记录真实。请放心,将其更正为“您的意思是我们的敌人,戈德斯坦和他的Eastasia队列。但是对于谁,他们却企图恶意地与他们接触?”
AJMansfield 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.