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)を引数にできない
とたくさん問題がある。何も満たせていない...
ここで、わからなかったので、答えを検索した。
で、出てきたのが、これ
コードがわかりやすかった。
この部分は、
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でメニューバー作ってみた
こんな感じ
ソースコード
#! 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であるので(微分のあれ)
こういう関係が成り立っていることがわかる。
これらを考慮すると、先ほどの v*dtは
)
から導き出すことができる。
これを同様にして、加速度を含んだ積分から導き出した物理の公式、
を用いて表してみれば、dxが出ると思った。
よって、
コイツに
を代入すると、
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