pwnable.kr(7)(1) ~input~

今回はなかば書き写す面が多いです。正直、わからないことが多かったので。
言わずもがな、使ってるpythonは2系です。

問題概要

以下のソースコードを実行して、flagを読み出す。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main(int argc, char* argv[], char* envp[]){
	printf("Welcome to pwnable.kr\n");
	printf("Let's see if you know how to give input to program\n");
	printf("Just give me correct inputs then you will get the flag :)\n");

	// argv
	if(argc != 100) return 0;
	if(strcmp(argv['A'],"\x00")) return 0;
	if(strcmp(argv['B'],"\x20\x0a\x0d")) return 0;
	printf("Stage 1 clear!\n");	

	// stdio
	char buf[4];
	read(0, buf, 4);
	if(memcmp(buf, "\x00\x0a\x00\xff", 4)) return 0;
	read(2, buf, 4);
        if(memcmp(buf, "\x00\x0a\x02\xff", 4)) return 0;
	printf("Stage 2 clear!\n");
	
	// env
	if(strcmp("\xca\xfe\xba\xbe", getenv("\xde\xad\xbe\xef"))) return 0;
	printf("Stage 3 clear!\n");

	// file
	FILE* fp = fopen("\x0a", "r");
	if(!fp) return 0;
	if( fread(buf, 4, 1, fp)!=1 ) return 0;
	if( memcmp(buf, "\x00\x00\x00\x00", 4) ) return 0;
	fclose(fp);
	printf("Stage 4 clear!\n");	

	// network
	int sd, cd;
	struct sockaddr_in saddr, caddr;
	sd = socket(AF_INET, SOCK_STREAM, 0);
	if(sd == -1){
		printf("socket error, tell admin\n");
		return 0;
	}
	saddr.sin_family = AF_INET;
	saddr.sin_addr.s_addr = INADDR_ANY;
	saddr.sin_port = htons( atoi(argv['C']) );
	if(bind(sd, (struct sockaddr*)&saddr, sizeof(saddr)) < 0){
		printf("bind error, use another port\n");
    		return 1;
	}
	listen(sd, 1);
	int c = sizeof(struct sockaddr_in);
	cd = accept(sd, (struct sockaddr *)&caddr, (socklen_t*)&c);
	if(cd < 0){
		printf("accept error, tell admin\n");
		return 0;
	}
	if( recv(cd, buf, 4, 0) != 4 ) return 0;
	if(memcmp(buf, "\xde\xad\xbe\xef", 4)) return 0;
	printf("Stage 5 clear!\n");

	// here's your flag
	system("/bin/cat flag");	
	return 0;
}

Stage1

	if(argc != 100) return 0;
	if(strcmp(argv['A'],"\x00")) return 0;
	if(strcmp(argv['B'],"\x20\x0a\x0d")) return 0;
	printf("Stage 1 clear!\n");	

この部分。
プログラムの引数の数を変化させて、内容も変える。

input2@ubuntu:~$ ./input `python -c "args=['a' for i in range(99)];args[ord('A')-1]='\x00';args[ord('B')-1]='\x20\x0a\x0d';print ' '.join(args)"`

でStage 1 clearかなと安易に思った。残念。

この問題点は、

  • ヌル文字で引数が止まる
  • スペース(\x20)を引数にできない
  • ラインフィード(\x0a)を引数にできない
  • キャリッジリターン(\x0d)を引数にできない

とたくさん問題がある。何も満たせていない...
ここで、わからなかったので、答えを検索した。
で、出てきたのが、これ

0x3f97.github.io

コードがわかりやすかった。
この部分は、
exec系のシステムコールを使って、引数を渡すようだ。
これを見て思ったのが、

ox.execv("/home/input2/input", ["input"]+args)

の部分で、自分で、引数の0番目を渡しているということ。
ここら辺は全部シェル(bash, zsh etc)がやってくれてるんだなという新たな知見を得ました。
なるほど。
じゃあ、やってみよう。

# /tmp/myfiles/stage1.py
import os
def main():
        args = ["0"] * 99
        args[ord("A")-1] = ""
        args[ord("B")-1] = "\x20\x0a\x0d"
        pid = os.fork()
        if pid == 0:
                os.execv("/home/input2/input",["input"]+args)

if __name__ == '__main__':
        main()
input2@ubuntu:/tmp/myfiles$ python stage1.py 
Welcome to pwnable.kr
Let's see if you know how to give input to program
Just give me correct inputs then you will get the flag :)
Stage 1 clear!

おっけい。
補足的な説明になるんだが、飛んだ先のパイプを使ったstage1クリアー方法はまちがっているんですよね。どうやら、execvが勝手に引数の後にヌル文字を追加してくれるので。
とりあえず、今日はここまでで。

AE-232Rが壊れちゃった

タイトル通り、壊してしまいました。

原因がわからないのがまた謎なんですよね。

ことの経緯

esp wroom 32 にファームウェアを書き込もうと思ってブレッドボードにセットしたんですよね。それで、電源装置から供給しました。
1 V ぐらいには 1 A近く流れてたんですよ。おかしい。
その後も線形で上がってく...

おかしいなぁと思って、IC触ったら激アツ。
これ壊れてるなぁと。

結論

原因がわからなかったのがまた辛いですね。配線は死ぬほど確認したので大丈夫だと思うんですけど、埃がたまりそうなところに野ざらしにしてたから...
とてもつらいです。
埃でショートが可能性一番ありうる。
ちゃんと埃の被らないところに置いておこうという教訓を得ました。

ARC103 C-/\/\/\/

なんとなく載せます

from collections import Counter


def main():
    n = int(input())
    v = [int(i) for i in input().split()]
    ans = 0
    odd = Counter(v[1::2])
    even = Counter(v[::2])
    odd_mosts = odd.most_common(2)
    even_mosts = even.most_common(2)
    if odd_mosts[0][0] == even_mosts[0][0]:
        if len(odd) == len(even) == 1:
            ans = n//2
        else:
            ans_sel = []
            ans_sel.append(n//2-odd_mosts[0][1]+n//2-even_mosts[1][1])
            ans_sel.append(n//2-odd_mosts[1][1]+n//2-even_mosts[0][1])
            ans = min(ans_sel)
    else:
        ans+=(n//2-odd_mosts[0][1])
        ans+=(n//2-even_mosts[0][1])
    print(ans)

うん。久々にやったからかすごい時間かかった気がした。

最近の近況報告

ToDoを真面目に作っている。自分で使うための。
githubに一応公開している

基本的に使っているものは

でバックエンドをたてた。
テストも真面目に書いてる。
アプリ側のUIとかまだ決まってないのでまだなんともって感じですけど。


前回作ったkivyのメニューバーなんだけど、クラスの構成ミスったなって感じがする。まだ、README.mdとか整えていないのでなんとも言えないが、直して公開したいなって思ってたり思ってなかったりする。


余談だが、昨日aitendoでTFTの2.8インチの半田付け必須のモジュール買ったんだけど、半田付けのところじゃない部分でミスってイキました。2000円無駄になりました。具体的には、基盤に付いてた表面実装の抵抗がクリップに引っかかってどっか飛んでいくという凄惨な事件です。何Ωだったのかもわからない。TFT本体は生きてるので、変換のフラットケーブルを入手できるか....

あと、全然格闘ゲームとかやらないんだけど、梅原さんの勝ち続ける意志力を読みました。

昨日変な時間に起きてしまい、夜中ずっと読んでたんです。めちゃめちゃ参考になりましたのん... 梅原さん本当に精神が強いなと思いました。弱々な僕とは全然違う... 読んでいて、めちゃめちゃかっこよかったです。やっぱり考えたり悩んだりするのって重要なんだなって思いました。ゲームだけじゃなくて、多分、世の中のあらゆることに通じているんじゃないかなと思うことしかなかったです。僕の中での何度も読みたい新書ランキングトップですね。前に、潔い生き方?みたいな本を読んだんですけど、塵ほどつまらなかったと感じたことがありました。それに比べると本当に実用的だし、それを実践する梅原さんはすごいなと。僕もちょっとずつ実践していきたいです。というかします。梅原さんみたいに幼少期から死ぬほど頑張って続けたものは遠い過去に自ら捨ててしまったけど、また1からでもやりたいです。

kivyでメニューバー作ってみた

環境

os x high Sierra
python 3.7.0
kivy 1.10.1

こんな感じ

f:id:b1u3:20180926225605g:plain

ソースコード

#! kivy 1.0.9
# example.kv

<MenuList>:
    canvas.before:
        Color:
            rgba: 1, 0, 0, .5
        Rectangle:
            pos: self.pos
            size: self.size


<MenuImage>:
    source: 'menu.png'
    keep_ratio: True


<MenuBar>:
    end: True
    canvas.before:
        Color:
            rgba: 1, 0, 0, .5
        Rectangle:
            pos: self.pos
            size: self.size

    MenuImage:
        center: 50, root.center_y
        size: 32, 32


<RootWidget>:
    MenuBar:
        pos: root.pos[0], root.height-90
        size: root.width, 90
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.image import Image
from kivy.properties import BooleanProperty, ObjectProperty
from kivy.logger import Logger
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.scrollview import ScrollView


class TestLabel(Label):
    """ For Testing MenuList """
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    def on_touch_down(self, touch):
        if self.collide_point(touch.x, touch.y):
            Logger.info(f'[{self.__class__.__name__}\t] {self.text} was touched.')
            return True
        return super().on_touch_down(touch)


class MenuList(ScrollView):

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.layout = GridLayout(cols=1, spacing=20, size_hint_y=None)
        self.layout.bind(minimum_height=self.layout.setter('height'))
        self.do_scroll_x = False
        self.add_widget(self.layout)
        MenuList.test_add_widget(self)

    def add_widget(self, widget, index=0, canvas=None):
        if isinstance(widget, GridLayout) or not self.children:
            super().add_widget(widget)
        else:
            if hasattr(widget, 'text_size'):
                widget.bind(size=self.__class__._update_each_text_rect)
            self.layout.add_widget(widget, index=index, canvas=canvas)

    @staticmethod
    def _update_each_text_rect(instance, value):
        instance.text_size = value[0]-10, value[1]

    @staticmethod
    def test_add_widget(menu_list):
        for i in range(5):
            lbl = TestLabel(text=f'Menu {i}', size_hint_y=None, height=40)
            menu_list.add_widget(lbl)


class MenuImage(Image):
    toggled = BooleanProperty(False)

    def on_touch_down(self, touch):
        Logger.debug(f'[{self.__class__.__name__}\t] touched')
        if self.collide_point(touch.x, touch.y):
            self.toggled = not self.toggled
            return True
        return super().on_touch_down(touch)

    def on_toggled(self, instance, value):
        Logger.info(f'[{self.__class__.__name__}\t] toggled to {value}.')
        if not hasattr(self.parent, 'toggled'):
            Logger.warning(f'[{self.__class__.__name__}\t] {self.parent.__class__.__name__}\
                            has no boolean attr toggled.')
        self.parent.toggled = value


class MenuBar(Widget):
    toggled = BooleanProperty(False)
    menu_list = ObjectProperty(None)

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.menu_list = MenuList()
        self.bind(size=self._update_size, pos=self._update_size)

    def on_toggled(self, instance, value):
        Logger.info(f'[{self.__class__.__name__}\t] toggled to {value}.')
        if self.menu_list is not None:
            if value:
                self.add_widget(self.menu_list)
                self._update_size(self, self.size)
            else:
                self.remove_widget(self.menu_list)

    def _update_size(self, instance, size):
        self.menu_list.size = (280, self.parent.height-90)
        self.menu_list.pos = self.parent.pos


class RootWidget(Widget):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)


class ExampleApp(App):
    def build(self):
        return RootWidget()


if __name__ == '__main__':
    ExampleApp().run()

途中まで書いた下書きが消えたので、以上です。

django-sslserverを入れた

最近のiOSアプリを開発していると、sslが効いてないサイトにアクセスするには別途、設定を加えなければならない。やってないからわからんけど、その設定を消し忘れてたりして、諸々を垂れ流したら大変なので、代替案を探した。その結果、djangoを使っていたので、django-sslserverを使うことにした。

環境

インストール

そのまま公式を見ればいいと思う

pip install django-sslserver

settings.pyに追記する

INSTALLED_APPS = [
    ...
    'sslserver'
]

migrate等はする必要はない。

manage.py runsslserver

デフォだと127.0.0.1:8000だが、これを初めて開くときは、信頼されていないので、safariを開くと、警告がでる。

証明書周り

runsslserverをすると、証明書の場所が表示されると思う。
openで開いて、証明書をダブルクリックすると、キーチェーンアクセスが開かれるので、左端のシステムをクリックして、証明書リストにfinderからdevelop.crtをドラッグする。ロックがかかっている場合は解除しておく。
そうすると、信頼されていない証明書が追加される。名前はlocalhost。それをダブルクリックして、別ウィンドウを開きつつ、信頼のところをクリックして、拡張する。「この証明書を信頼するとき」のリストを常に信頼するに変えると他の部分も自動的に変わるので、保存する。

またrunsslserverして、httpsでアクセスすると入れる。

delta-timeについて

kivyのClockのところを読んでいたら、コールバックの引数にdt(delta-time)を渡していた。

んで、dtってなんだろうって調べた。

これは前のフレームとの時間差らしい。

だから、はやさ v pix/sで進ませたければ、そのポジションに前の時間から今の時間の間に進む距離を足せばよいので、

(呼び出される瞬間の位置) = (前の位置) + v*dt

となる。

こっからは自分で考えたんだが、
加速度を用いて
x+=の形にできないだろうかと。

ここで、さっきの式の v*dtはdxであるので(微分のあれ)

 dx = x_{n} - x_{n-1}

こういう関係が成り立っていることがわかる。

これらを考慮すると、先ほどの v*dtは

 dx = v * n * dt + x_{0} - (v * (n-1) *dt + x_{0})

から導き出すことができる。

これを同様にして、加速度を含んだ積分から導き出した物理の公式、

 x = \frac{1}{2}at^{2} + vt + x_{0}

を用いて表してみれば、dxが出ると思った。

よって、

 dx = \frac{1}{2}at_{n}^{2} + vt_{n} + x_{0} - (\frac{1}{2}at_{n-1}^2+vt_{n-1}+x_{0})

コイツに

 t_{n} = n×dt

を代入すると、

 dx = \frac{1}{2}a(2n-1)dt^{2}+vdt

nが消えないので、
x+=の形では表せないようだ。

コード書くときは位置の変数に公式から出した値をぶち込むしかなさそうだ。

ただし、こんな書き方はある

In [19]: def test(dt, v, a):
    ...:     if 10%dt != 0:
    ...:         return
    ...:     x = 0
    ...:     for i in range(10//dt):
    ...:         x += (1/2*a*(2*float(i+1)-1)*dt**2+v*dt)
    ...:     print(x)
    ...:

In [20]: test(2,3,4)
230.0

In [21]: test(5,3,4)
230.0