flip

int (*flip(int (*fun)(int,int)))(int,int)
{
    unsigned char *func = (char*)malloc(1000);
    func[ 0]=0x8B;func[ 1]=0x44;func[ 2]=0x24;func[ 3]=0x04;
    func[ 4]=0x87;func[ 5]=0x44;func[ 6]=0x24;func[ 7]=0x08;
    func[ 8]=0x89;func[ 9]=0x44;func[10]=0x24;func[11]=0x04;
    func[12]=0xB8;*(int**)(func+13)=(int*)fun;
    func[17]=0xFF;func[18]=0xE0;
    return (int(*)(int,int))func;
}

flipのしていることは、アセンブラに直せば非常に単純でして

mov   eax,[esp+4]
xchg  eax,[esp+8]
mov   eax,[esp+4]
mov   eax,[flipの引数に与えられたアドレス]
jmp   eax

という命令を func の先に書き込んでこれを関数ポインタにキャストして返す
、という感じになります。[esp+4],[esp+8]は引数なので、それを無理やり xchg で入れ替えた後に、 jmp で入れ替わる元の関数に飛んでいるのです。絶対ジャンプにするために一旦レジスタに入れております。
K のしていることは
たとえば、
K(1000)ならば

mov  eax,1000
ret

というコードを作って返す、です。

ついでなので S K K を実行したときにどのようなコードが吐かれるかを書いておきます。
S K

55               PUSH EBP
8BEC             MOV EBP,ESP
53               PUSH EBX
56               PUSH ESI
57               PUSH EDI
6A 2D            PUSH 2D
B8 A0174000      MOV EAX,stack.malloc
FFD0             CALL EAX
83C4 04          ADD ESP,4
BE F8914C00      MOV ESI,DATA
8BF8             MOV EDI,EAX
B9 2D000000      MOV ECX,2D
F3:A4            REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[> ;文字列転送命令DATAのところを2D文字移す。
8B55 08          MOV EDX,DWORD PTR SS:[EBP+8]
8950 0B          MOV DWORD PTR DS:[EAX+B],EDX              ;MOV EAX,0 の 0 を正しい命令に書き換える。
90               NOP
90               NOP
5F               POP EDI
5E               POP ESI
5B               POP EBX
5D               POP EBP
C3               RETN
CD CD            INT 0CD
CD CD            INT 0CD
CD CD            INT 0CD
CD CD            INT 0CD
CD CD            INT 0CD
CD CD            INT 0CD
CD CD            INT 0CD
CD CD            INT 0CD
CD CD            INT 0CD
CD
:DATA
55               PUSH EBP
8BEC             MOV EBP,ESP
53               PUSH EBX
56               PUSH ESI
57               PUSH EDI
8B55 08          MOV EDX,DWORD PTR SS:[EBP+8]
52               PUSH EDX
B8 00000000      MOV EAX,0
FFD0             CALL EAX
83C4 04          ADD ESP,4
50               PUSH EAX
8B55 08          MOV EDX,DWORD PTR SS:[EBP+8]
52               PUSH EDX
B8 stack.k       MOV EAX,stack.k
FFD0             CALL EAX
83C4 04          ADD ESP,4
FFD0             CALL EAX
83C4 04          ADD ESP,4
5F               POP EDI
5E               POP ESI
5B               POP EBX
5D               POP EBP
C3               RETN

S K K

55               PUSH EBP
8BEC             MOV EBP,ESP
53               PUSH EBX
56               PUSH ESI
57               PUSH EDI
8B55 08          MOV EDX,DWORD PTR SS:[EBP+8]
52               PUSH EDX
B8 stack.k       MOV EAX,stack.k
FFD0             CALL EAX
83C4 04          ADD ESP,4
50               PUSH EAX
8B55 08          MOV EDX,DWORD PTR SS:[EBP+8]
52               PUSH EDX
B8 stack.k       MOV EAX,stack.k
FFD0             CALL EAX
83C4 04          ADD ESP,4
FFD0             CALL EAX
83C4 04          ADD ESP,4
5F               POP EDI
5E               POP ESI
5B               POP EBX
5D               POP EBP
C3               RETN

で、この関数が恒等写像であるのは当然でしょう。

Sコンビネータで、mallocを直書きした理由にもつながる話を。バッファーオーバーフロー攻撃が成功すると、その後は色々なAPIを漁りに行きます。それは実は結構大変です。侵入したコードは何も知らない状態からどこに何の関数があるのかを探さないといけないのですから。ところが、ここでライブラリのリンク順序が決まっていると手元で調べて、そのアドレスを埋め込んでおくという手法が使えます。そこで linux ではセキュリティ上の理由からランダムな順序でライブラリをリンクしているらしいです。

前半は下記。
http://d.hatena.ne.jp/nuc/20051101/p1 関数型C言語
http://d.hatena.ne.jp/nuc/20051101/p2 K
http://d.hatena.ne.jp/nuc/20051102/p5 Sコンビネータ
http://d.hatena.ne.jp/nuc/20051102/p6 スタック