Category: 雑記

MS 実装の csharp コマンドである “csi” コマンドを使ってみた。


みむらです。

今朝方、新潟の日本酒を飲みに行こうかなぁ・・ ( http://anisec.jp/yuzawa/ ) と思っていた所、
鋭敏電子の秋月さんも「こっ・・これはっ・・!」となる記事を見かけ、
いても経ってもいられず、移動中の車内で試してみることにしました。

記事としては次の記事。
http://blogs.msdn.com/b/visualstudio/archive/2015/10/08/visual-studio-2015-update-1-ctp.aspx

Visual Studio 2015 の Update 1 CTP がリリースされましたよという記事なのですが、
その中に、”Visual C# Interactive Compiler..” というものがありまして、
どうも見てみると、 mono の csharp コマンドのようなことをするプログラムのようで、
これは確かめなければっ・・! ということで現在に至ります。


使ってみた:

image

TAB による推測が出ないので、少し入力しづらいという点はありますが、
C# らしいコードを普通に書いて、ごにょごにょできるのはとても素晴らしいと思います。


インストール方法:

ダウンロードの URL がとても見つけづらいのですが、
Visual Studio 2015 Update 1 CTP
ここからダウンロードが可能です。

セットアップを開始すると、
image

こんな感じのおなじみの画面でセットアップが行われていきます。

終わりましたら、 「Visual Studio コマンドプロンプト」から “csi” コマンドで起動できます。

Windows で特定の IP アドレスが静的に設定できない場合


みむらです。ちょっとしたメモ。

色々と弄っていましたら、IP アドレスの静的な設定で
特定のアドレスだけ設定しようとしてもその値がクリアされるという問題が起きていました。

その解決法を見つけましたのでメモ。


netsh int ipv4 reset netsh int ipv6 reset

 

早い話が netsh コマンドを使って全部のアダプタ設定をリセットする、という内容です。

コマンドを入力した後マシンを再起動し、
IP アドレスを設定し直すとうまくいくと思います。

DNS リゾルバキャッシュの内容を表示する


どうもみむらです。

Windows は内部に DNS キャッシュを持っていまして、
その中身というのはやはり見てみたいものです。

ただ見るだけであれば、
ipconfig /displaydns
と打てば一覧で出てきてしまいますが、
今回は API を呼び出して取得してみます。


情報を取得するためには、dnsapi.dll にある “DnsGetCacheDataTable” という API を呼び出します。

#include <Windows.h>
#include <WinDNS.h>
#pragma comment(lib,"Dnsapi.lib")

typedef LSTATUS(WINAPI *PDnsGetCacheDataTable)(PDNS_RECORD*);

void main()
{ 
	PDNS_RECORD entry; PDnsGetCacheDataTable dgcdt = (PDnsGetCacheDataTable)GetProcAddress(LoadLibrary(L"dnsapi.dll"), "DnsGetCacheDataTable");
	dgcdt(&entry);
	DnsRecordListFree(entry, DnsFreeRecordList);
}

ヘッダファイルに書かれていない API ですので、GetProcAddress で関数アドレスを取得して
動的に呼び出してやる必要があります。

image

実行しますとこのように、 “pNext” に次の情報が入った
「片方向のリンクリスト」の形で情報が入ったデータが返されます。

 

さらにここから、IP アドレスも求めるということであれば、
DnsQuery 関数を “DNS_QUERY_NO_WIRE_QUERY” ( キャッシュのみに問い合わせるオプション )を付けて呼び出すことで求まります。

#include <Windows.h>
#include <WinDNS.h>
#include <stdio.h>

#pragma comment(lib,"Dnsapi.lib")
#pragma comment(lib,"ws2_32.lib")

typedef LSTATUS(WINAPI *PDnsGetCacheDataTable)(PDNS_RECORD*);

void main()
{
	PDNS_RECORD entry, orig_entry, data;

	PDnsGetCacheDataTable dgcdt = (PDnsGetCacheDataTable)GetProcAddress(LoadLibrary(L"dnsapi.dll"), "DnsGetCacheDataTable");

	dgcdt(&orig_entry);
	entry = orig_entry;

	while (entry != NULL && entry->pNext != NULL)
	{
		DnsQuery(entry->pName, DNS_TYPE_A, DNS_QUERY_NO_WIRE_QUERY, 0, &data, 0);

		if (data != NULL)
		{
			IN_ADDR addr;

			addr.S_un.S_addr = data->Data.A.IpAddress;
			printf("%S : %s\n", entry->pName, inet_ntoa(addr));
		}

		entry = entry->pNext;
	}

	DnsRecordListFree(orig_entry, DnsFreeRecordList);
}

実行結果としてはこんな感じ:

image

・・・私がどこによくアクセスするかが丸わかりですね・・


というわけで・・
このような感じで、リゾルバキャッシュのデータを取り出すことが出来ました。

ですが、一点注意点として
“DnsGetCacheDataTable” 関数は MSDN にて明確にドキュメント化されていません。

ですので、今後呼び出し方法が変更される可能性は十分にあります。

使う場合は “現状は動く” 程度でとらえて頂ければと思います。

vCenter Appliance 5.x を 6 にアップグレードする


みむらです。
暑い日が続いておりますがいかがお過ごしでしょうか。

夏と言えば暑い。熱いなら、サーバの台数を減らせばいい。
それなら VMware ESXi と。そうなるわけです。
何もおかしいところはない、実に自然な思考回路です。

 

冗談は置いておいて。

ESXi 5.5 と vCenter Appliance 5.5 での組み合わせで動かしていますが、
6.0 も出たことですし、アップグレードしようということでやってみました。


1.VMware vCenter Server Appliance をダウンロード

2. 古い VMware vCenter Server Appliance の設定を変更する

変更する箇所は次の2点です。

・SSO (シングルサインオン) を設定する
・SSH ログインを有効にする

設定を変更するには:

VMware vCenter Server Appliance の設定画面を開いて設定を行います
( https://(サーバ名):5480/ にアクセスして出てくる画面です )

SSO ( シングルサインオン ) を設定する:

設定画面の “vCenter Server” タブの “SSO” をクリック。

image

他の認証システムを使用する場合は “SSO deloyment type” を変更すれば可能(だと思います)

小規模なシステムであれば “embedded” で大丈夫かと思います。
後は、設定したいパスワードを入力し、右側の “Save Settings” をクリックすれば
設定完了です。

 

SSH ログインを有効にする:

“Admin” タブに移動し、
画面下の “Administrator SSH login enabled”“Certificate regeneration enabled” にチェックを入れ
”Submit” を押します。

 

3. VMware vCenter Server Appliance をアップグレード

1 でダウンロードした VMware VCSA ( VMware –VCSA-all-6.x.x… .iso ) のディスクを
マウント or 書き込んだディスクを読み込んで中のファイルを使えるようにします。

3.1. VMware Client Integration Plugin をインストール

ディスク内の “vcsa” フォルダ内の “VMware-ClientIntegrationPlugin..” をインストールします。

3.2. アップグレード画面を出す

ディスク直下の “vcsa-setup.html” をダブルクリックし、画面を表示します。

image

3.3. 後はウィザードに従ってアップグレードを行う

あとはこんな感じで待ちます・・・

image


長々と時間が掛かりますが、
完了すると古い vCenter がシャットダウンされ、新しい vCenter が立ち上がっています。

あとは、新しい vCenter のキーをインストールすれば完了です。

その他必要に応じて、Update Manager などのアップグレードや
ESXi のアップデートを行ってください。

DEFCON CTF 23 Quals – catwestern Writeup


ご無沙汰してます。みむらです。
今年は、某「みかか」な場所で Team Enu のみなさんと一緒に参加してきました。

やはり合宿形式でやるというのは面白いですし、
出来る人が周りに居ますと、それだけでかなり成長できるなということを強く思いました。
・・・来年もこういう感じで出来たらいいなぁ・・と思うそんな今日この頃です。

というわけで、ちゃんと最後まで自分でやりきった内容の Write-up ということで
catwestern のWrite-up を。

 

catwestern


指定されたサーバに接続すると次のようなバイナリデータが送信されてきます。

image

 

上の方は「レジスタ」の情報で、
”About to send ** bytes:” の先に x86_64 っぽいバイナリが
送られてきていることがわかるかと思います。

 

ここで mzyy94 (みっきー)さんが
「rax=… をそのまま返すと、応答が変わる!」と教えてくれまして
実行してその結果を返せばいいのかな、ということでやってみました。

 

Code:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/mman.h>
 
static char* code;
static unsigned long reg[15];
 
void main(void)
{
    int sock;
    struct sockaddr_in server;
 
    memset((void*)&server,0,sizeof(server));
    server.sin_addr.s_addr = inet_addr("52.74.101.145");
    server.sin_family = AF_INET;
    server.sin_port = htons(9999);
 
    sock = socket(AF_INET,SOCK_STREAM,0);
    if(sock == -1) return;
 
    if(connect(sock, (struct sockaddr*)&server, sizeof(server)) < 0)
        return;
 
    while(1)
    {
        char buf[4192];
        int i,codesize,pagesize;
 
        memset(buf,0,sizeof(buf));
        read(sock,buf,sizeof(buf));
 
        printf("INPUT : \n%s\n",buf);
 
        {
            char *tp;
         
            tp = strtok(buf,"\n");
            for(i = -1; tp != NULL; i++)
            {
                if(strstr(tp,"=") != 0)
                    reg[i] = strtouq(strstr(tp,"=")+1,NULL,0);
                tp = strtok(NULL,"\n");
            }
        }

        read(sock,buf,sizeof(buf));
        codesize = atoi(buf+0x37);
 
        if(codesize == 0)
            break;
 
        pagesize = sysconf(_SC_PAGE_SIZE);
        code = memalign(pagesize,pagesize);
 
        memset(code,0xC3,pagesize);
        memcpy(code,buf+0x42,codesize);
        printf("CODESIZE : %d bytes.\n",codesize);
 
        if(mprotect(code,pagesize,PROT_READ | PROT_EXEC) < 0)
        {
            free(code);
            return;
        }
 
        printf("EXECUTE..");
 
        asm volatile ("movq (reg),%rax");
        asm volatile ("movq (reg+8),%rbx");
        asm volatile ("movq (reg+16),%rcx");
        asm volatile ("movq (reg+24),%rdx");
        asm volatile ("movq (reg+32),%rsi");
        asm volatile ("movq (reg+40),%rdi");
        asm volatile ("movq (reg+48),%r8");
        asm volatile ("movq (reg+56),%r9");
        asm volatile ("movq (reg+64),%r10");
        asm volatile ("movq (reg+72),%r11");
        asm volatile ("movq (reg+80),%r12");
        asm volatile ("movq (reg+88),%r13");
        asm volatile ("movq (reg+96),%r14");
        asm volatile ("movq (reg+104),%r15");
         
        asm volatile ("call *code");
 
        asm volatile ("movq %rax,(reg)");
        asm volatile ("movq %rbx,(reg+8)");
        asm volatile ("movq %rcx,(reg+16)");
        asm volatile ("movq %rdx,(reg+24)");
        asm volatile ("movq %rsi,(reg+32)");
        asm volatile ("movq %rdi,(reg+40)");
        asm volatile ("movq %r8,(reg+48)");
        asm volatile ("movq %r9,(reg+56)");
        asm volatile ("movq %r10,(reg+64)");
        asm volatile ("movq %r11,(reg+72)");
        asm volatile ("movq %r12,(reg+80)");
        asm volatile ("movq %r13,(reg+88)");
        asm volatile ("movq %r14,(reg+96)");
        asm volatile ("movq %r15,(reg+104)");
         
        printf("DONE.\n");
        free(code);
 
        memset(buf,0,sizeof(buf));
        sprintf(buf,"rax=0x%llx\nrbx=0x%llx\nrcx=0x%llx\nrdx=0x%llx\nrsi=0x%llx\nrdi=0x%llx\nr8=0x%llx\nr9=0x%llx\nr10=0x%llx\nr11=0x%llx\nr12=0x%llx\nr13=0x%llx\nr14=0x%llx\nr15=0x%llx\n",reg[0],reg[1],reg[2],reg[3],reg[4],reg[5],reg[6],reg[7],reg[8],reg[9],reg[10],reg[11],reg[12],reg[13]);
 
        printf("OUTPUT :\n%s\n",buf);
        write(sock,buf,strlen(buf));
    }
}

 

内容としては、レジスタの初期値を持ってきて、
自分自身に対してその値を設定 → 実行 → レジスタの値を取得して送り返す。
という流れになります。

..そんな感じで実行しますと、

FLAG IS : Cats with frickin lazer beamz on top of their heads!

ということで返答が帰ってきますんで、これを送ると得点がえられました。

 


余談:

このあたりに後ろ姿が..
https://www.ntt.com/wideangle_security/data/sec_repo.html

また、今回こそは “Python コード書くぞ!!” と思っていたんですが、
気づいたら C と C# しか書いていませんでした。
(特に、「コード貼ってよ」→「C# ですがいいですか」→「C#… orz」 の流れは辛かったです)

次回こそは・・次回こそは・・!
(Babyecho も Pwn も C# で取り組んでました.  BitConverter.GetBytes() は偉大です.

…この問題の Write-up も、他の人はみんな通信部分は Python でやってるんですよね。
うーんやっぱりやらないとなぁ。