Skocz do zawartości

Reverend

Członkowie
  • Postów

    9
  • Dołączył

  • Ostatnio

    Nigdy

Reverend's Achievements

Newbie

Newbie (1/14)

0

Reputacja

  1. Ok, błąd znaleziony. Jednak chodziło o synchronizację. To prawda, każdy wątek miał swoją pamięć. Ale nie zauważyłem, że sama procka licząca ma swoje globalne dane, które wątki współdzieliły. Dzięki Gynvael za odpowiedź :)
  2. Napisałem prostego bruteforce'a. Aby przyspieszyć działanie i wykorzystać możliwości obu rdzeni, podzieliłem liczenie na dwa wątki (parzyste/nieparzyste). Dało to wymierny efekt - zamiast 50% zużycia procka, mam teraz średnio 92%. Każdy wątek ma wydzielony kawałek pamięci, do którego swobodnie pisze i czyta. Jest tylko jeden bajt współdzielony - flaga określająca czy globalnie znaleziono rozwiązanie czy nie. Niestety program mi nie działał. Nie miałem jak go debugować, bo Olly pod x86-64 nie działa, fdbg wykrzacza się, a WinDbg nie umiem używać. Więc klasycznie napisałem sobie zrzucanie każdego pośredniego wyniku liczenia do pliku. I nagle bruteforce zaczął działać! Dodałem tylko linijkę z WriteFile. Kiedy usunę tą linijkę, na powrót bruteforce nie działa. Jak to jest możliwe? Linijka kodu z WriteFile, jest dla obliczeń niczym "nop". W żaden sposób nie zmienia toku liczenia. Czy ktoś z was się może spotkał z czymś takim? Dla mnie to jakieś niepojęte jest. Przychodzi mi do głowy tylko jeden scenariusz, choć jest on trochę naciągany. Jak wiadomo pisanie do pliku, czyli operacja I/O jest powolna i wtedy wątek/proces oddaje moc obliczeniową, bo i tak jej nie wykorzysta. Może jeden z wątków jest głodzony? Bez tego spowalniacza I/O, jeden wątek pożera całą moc obliczeniową, a drugi stoi w miejscu. Kiedy jednak dodać ten WriteFile, to zaborczy wątek siłą rzeczy musi oddać procesor i wtedy nie ma mowy o głodzeniu. Tylko, że wątki są równouprawnione i nawet przy jednym procesorze każdy powinien jakiś kwant czasu dostać. Przy dwóch prockach głodzenie jednego z wątków wydaje się absurdem, choć kto wie. Poza tym liczę skrycie, że nie o to chodzi - bo niby jak to ma być, mam bruteforce'a spowalniać? :P
  3. Jest takie API, które wyświetla DialogBoxa ze wskazanego adresu w pamięci, a nie z zasobów. Co prawda nigdy nie udało mi się tego użyć, ale nadzieja jest :P. Warto sprawdzić fasma, bo tam zasoby są tworzone w pliku PE przy użyciu specjalnych makr. Można łatwo te makra dostosować i tym samym struktura DialogBoxa zostanie zapisana nie w .rsrc, ale w dowolnym miejscu. A tutaj link do wymienionego API: http://msdn.microsoft.com/en-us/library/ms645461(VS.85).aspx" title="http://msdn.microsoft.com/en-us/library/ms645461(VS.85).aspx">DialogBoxIndirectParam
  4. Musisz stworzyć sobie pewien interfejs. Pamiętaj, że przy wywołaniu LoadLibrary() wykonywany jest kod inicjalizujący w tej bibliotece, zwracający 0 jeśli się powiodło. Twój interfejs powinien nakazywać, aby to w tej części biblioteki plugin się "przedstawił". W ten sposób dowolny .dll nie będzie rozpoznawany jako plugin. Dalej to już wiele zależy od specyfiki głównego, "pluginowalnego" programu. Jeśli np. chcesz, aby kontrolę nad częścią zasobów (np. obsługiwanie plików mp3) sprawował dany plugin, to określasz sobie zestaw funkcji, które dany plugin musi posiadać oraz jakąś procedurę, która poinformuje ten plugin, że uzyskał kontrolę nad zasobem. Przykład: Program otwiera pliki i zależnie od rodzaju coś dalej z nimi robi. Ale te działania na różnych typach plików nie są wbudowane w program, ale są pluginami. Główny program wymaga, by plugin przedstawił się - czyli wskazał jakie pliki umie obsługiwać. Wymagana jest także implementacja metod: bool acquireResourceControl() - do poinformowania plugina o tym, że "został wybrany", bool processCommand() - do oddania obsługi konkretnego żądania do plugina, itp. No tak jak mówię, to wszystko zależy od specyfiki programu. Jedno co musisz zrobić to ustalić zestaw metod, które każdy plugin musi zaimplementować. Będą to metody do komunikacji. Zobacz sobie na szablon plugina do PEiDa. Mamy LoadDLL(), które zwraca string z nazwą. Mamy DoMyJob(). To najprostszy możliwy schemat :) #include #include "defs.h" DWORD DoMyJob(HWND hMainDlg, char *szFname, DWORD lpReserved, LPVOID lpParam) { //hMainDlg: HWND of PEiD window //szFname: Filename //lpReserved: PEiD passes 'PEiD' as the value //lpParam: NULL passed, for future use // Write your main code here return 1; } LPSTR LoadDll() { return "Name of the plugin"; } BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { switch(fdwReason) { case DLL_PROCESS_ATTACH: break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: break; } return TRUE; }
  5. Rozbiłem na bajty ten ciąg co ma utworzyć 26 zer: 1 00001001 - 2 zera 1 00001010 - 3 zera 1 00001011 - 4 zera 1 00001100 - 5 zer 1 00001101 - 6 zer 1 00001101 - znowu 6 zer2+3+4+5+6+6 = 26 Czyli generalnie to co napisałem w pierwszym moim poście jest dobre, z tym, że tam miałem drobny błąd. Pisałem, że kod 9 wypisze jedno zero, kod 10 dwa zera, itd, kiedy to kod 9 wypisuje już dwa zera, kod 10 trzy... Idea jest taka jak pisałem. A jeżeli rzeczywiście chcesz implementować dekompresję samemu, a nie ripować to z programu, to ja od razu odradzam asm albo C. Najlepiej chyba użyć C++ z STLem albo w ogóle jakiegoś Pythona, gdzie masz dostępną mapę asocjacyjną (tablicę haszową). EDIT: Chociaż w tym drugim wypadku coś nie gra:1 00001110 - 7 zer 1 00011001 - 8 zer 1 00011010 - 9 zer 1 00001011 - 4 zera7+8+9+4=28 Na pewno tam w nieskompresowanych danych było 27, a nie 28 zer?
  6. Ten algorytm to Lempel-Ziv-Welsch, czyli LZW :). Wiem, bo kiedyś to w asmie klepałem :P. Właściwie tutaj jest jakaś modyfikacja, ale generalnie idea jest zachowana. Algorytm działa tak: 0. Początkowo słownik jest pusty --- 1. Pobierz bajt z wejścia 2. Jeżeli nie masz takiego w słowniku to dodaj go tam i przypisz mu pierwszy wolny nr. Następnie wypisz bit 0 oraz jawnie ten cały bajt 3. Jeżeli masz, to wypisz bit 1 oraz nr w słowniku. Następnie tą parę bajtów dodaj do słownika z kolejnym numerem 4. Pętla ;) Dlaczego tak? Pierwsze bajty są wypisywane kolejno poprzedzone zerem (bo jak na razie są wyjątkowe, nie było wcześniej takich). Pierwszy bajt jaki się powtarza to 00000000 i jak sprawdzisz ma on przypisany nr 9 w słowniku (zaczynamy liczyć od zera). Więc zamiast powtarzać ten bajt wypisujemy bit 1 oraz nr w słowniku, czyli binarnie 00001001. Ale zapamiętujemy, że od teraz jeśli wystąpia 2 bajty 00000000 pod rząd to mają one w słowniku kolejny nr, czyli 10 dziesiętnie. I tak rzeczywiście się dzieje, więc znowu wypisujemy bit 1 oraz nr w słowniku, czyli 00001010. Teraz zapamiętujemy, że 3 bajty 00000000 pod rząd mają nr w słowniku 11 dziesiętnie. I to tak dalej idzie. Zauważ, że ten ciąg, bitów, które tam wypisałeś da właśnie 26 zer w końcu, a później 27. Nie wiem jak to prościej wytłumaczyć, ale na pewno chodzi o ten algos. Poczytaj o LZW, przeanalizuj co tu pisałem, a jakby co postaram się jaśniej jeszcze wytłumaczyć :)
  7. Też tego używałem na Linuksie x86-64. Ale z tego co pamiętam stanęło na GDB jednak. Chociaż prawda też taka, że na Linuksie to w asmie praktycznie nic nie pisałem i pod GDB miałem miłe 'debug symbols' wygenerowane przez GCC :). A tak pisząc właśnie w fasmie, który nie wspiera żadnych informacji dla debugera to GDB może być niezłą męczarnią
  8. Kiedyś też SoftIce u mnie panował, ale zagłosowałem na OllyDbg, bo obecnie tylko go używam. W sumie dopiero za trzecią próbą się do niego przekonałem. Co ciekawe nawet teraz potrafię odkryć jakąś ciekawą funkcję Olly'ego. Niestety do niektórych rzeczy trzeba mieć ustawiony focus na dobrym okienku, kliknąć prawym, przedzierać się przez skomplikowane menu, itd. Ale do standardowego debugowanie jest idealny ;)
  9. Ja zawsze korzystam z biblioteki msvcrt.dll, która z tego co wiem jest dostępna w każdym Windowsie. Kod (fasm): locals argc dd ? argv dd ? endl lea eax, [argc] lea edx, [argv] cinvoke __getmainargs, eax, edx, esp, 0, eaxPóźniej odwołuję się już do argc i argv niczym w czystym C
×
×
  • Utwórz nowe...