herm1t LIVE!ng room - nspr4!PR_Write [entries|archive|friends|userinfo]
herm1t

[ website | twilight corner in the herm1t's cave ]
[ userinfo | ljr userinfo ]
[ archive | journal archive ]

nspr4!PR_Write [Mar. 9th, 2015|03:05 pm]
Previous Entry Add to Memories Tell A Friend Next Entry
[Tags|, , , , , , , , ]
[Current Mood | bitchy]

Так как никто ничего дельного не пишет, приходится копаться во всяком УГ, типа Hand of Thief. Оно находит nspr4!PR_Write из проинжектированной либы, и затем затирает пролог jmp (0xe9). Естественно, так как FF хрень многопоточная, то при постоянной перезаписи пролога, креш броузера - это вопрос времени. (У мну пять секунд). Так как, NSPR подгружается динамически, то у PR_Write нет записи в GOT/PLT и PLT Redirection/GOT poisoning работать не будет. Так что нужно либо хватать dlsym до старта, либо внимательнее смотреть на PR_Write, который изначально определен вот так (mozilla/nsprpub/pr/src/io/priometh.c , теперь понятно на чем они сидят ;-):
PR_IMPLEMENT(PRInt32)
PR_Write(PRFileDesc *fd, const void *buf, PRInt32 amount)
{
        return((fd->methods->write)(fd,buf,amount));
}
Или в коде:
  33f1a0e7e0:   48 8b 07                mov    (%rdi),%rax
  33f1a0e7e3:   48 8b 40 ??             mov    0x??(%rax),%rax
  33f1a0e7e7:   ff e0                   jmpq   *%rax
  33f1a0e7e9:   0f 1f 80 00 00 00 00    nopl   0x0(%rax)
Это я к чему. Не нужно ничего затирать и копировать байты. Нужно затереть ее один раз, а оригинальную функцию положить в отдельно выделенную память и звать ее оттуда. Или, если учесть, что struct PRIOMethods ни разу не менялся - звать напрямую, едва ли его поломают. Вот так:
static int pr_write(void *handle, void *buffer, int length)
{
        ...
        return ((int (*)(void*,void*,int))
          (*(void***)handle)[а тут кто-то в исходники полезет ;-)])
            (handle, buffer, length);
}
Так что правильно, что ХоТ попал под блэк, на хуй, на хуй такой код. А у мну POST-запросы логируются на отлично:
POST /editjournal.bml HTTP/1.1
Host: lj.rossia.org
Content-Type: application/x-www-form-urlencoded ...
Чего и вам желаю. В следующий раз еще расскажу, как правильно делать GOT poisoning в рантайме, чтобы ничего не затирать и не копировать. upd. для форм-граббера под FF есть еще более эфектное решение, в котором не нужно ничего патчить, но это совсем другая история.
LinkLeave a comment

Comments:
[User Picture]
From:[info]geladen
Date:March 9th, 2015 - 05:10 pm
(Link)
ишьты, хитренько. мерси.

> В следующий раз еще расскажу [...]

а вот это бы я тоже с большим интересом почитал.
[User Picture]
From:[info]herm1t
Date:March 9th, 2015 - 05:27 pm
(Link)
Если коротко, то либа инжектится целиком __libc_dlopen_mode(..., RTLD_LAZY), именно LAZY, а не NOW, в конструкторе либа из своего _DYNAMIC берет GOT, из GOT[1] - link_map, из link_map - _DYNAMIC процесса, из него .dynsym, .dynstr, .rela.plt, в RELA находится нужная функа (ELF64_R_SYM(rel[i].r_info) - это индекс в .dynsym), а r_offset указывает на ее GOT-entry, который нужно сохранить и затереть указателем на свою функу. Как-то так.
[User Picture]
From:[info]geladen
Date:March 9th, 2015 - 06:12 pm
(Link)
о! мерси!
помусолю на досуге.
[User Picture]
From:[info]herm1t
Date:March 13th, 2015 - 05:13 pm
(Link)