Sunday, January 02, 2011

Setting the MAC address on an Inspiron 6400

Dell Wireless 1500 802.11n WLAN Mini-card

The card is actually based on a Broadcom BCM4328 chip, and the drivers are from Broadcom. I'm currently using driver version 5.60.48.35. The advanced tab of properties in Device Manager allows a "Locally Administered MAC Address" to be assigned. It is an 8 byte (or 12 character) hexadecimal string using uppercase letters. It must be a locally administered unicast address, meaning the least significant bits of the first byte are 10 (and therefore the second character is 2, 6, A or E). An address which doesn't follow this format will be accepted without any error messages, but the driver will ignore it, and the card will continue to use its original address.

I wonder if the use of a locally administered address is being enforced to prevent copying of other addresses and circumvention of MAC address filtering on wireless networks. I also wonder if it would be easy to reverse-engineer the driver and remove this limitation. However, I currently have no need for this so I will not attempt it.

Broadcom 440x 10/100 Integrated Controller

I'm currently using driver version 4.60.0.1. There was no option for changing the MAC address in the advanced tab of properties in Device Manager. However, the address can be changed via the registry. The registry entry needs to be located within the adapter's numbered key in "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}", the same key where "DriverDesc" is "Broadcom 440x 10/100 Integrated Controller". Its name needs to be "NetworkAddress" and it must be of REG_SZ (string) type. The address must be entered as a hexadecimal number, with uppercase letters and no separators between bytes. After changing this entry, the adapter has to be disabled and re-enabled for it to take effect. (When changing the address via the properties dialog, Windows does this automatically.)

It's possible to add a "Locally Administered MAC Address" item to the advanced properties tab. All the items there are described by keys in the registry in the "Ndi\params" key within the adapter's key. Since the wireless card sets the MAC address in the same way, you can export the wireless card's "NetworkAddress" key, change the adapter number in the .reg file to the 440x, and then import the .reg file. Alternatively, use the following, also making sure that the number ("0007" here) matches the number of the 440x adapter's key:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\0007\Ndi\params\NetworkAddress]
"ParamDesc"="Locally Administered MAC Address"
"type"="edit"
"LimitText"="12"
"UpperCase"="1"
"default"=""
"optional"="1"


The 440x only demands that you use a unicast address, meaning the least significant bit of the first byte is 0 (and therefore the second character is even). If the bit is not zero, the driver will ignore the address and continue using the original address. Unlike with the wireless card, the locally administered bit does not need to be set. This means the mac address of another device can be cloned or spoofed.

Sunday, December 12, 2010

A stripped-down Rockbox build for the Archos V2 Recorder

The Archos V2 Recorder has only two megabytes of RAM. This RAM is used for the software running on the device, and whatever RAM remains may be used as a buffer to store MP3 data. It's a very small amount of RAM and even at 128 kbps, most songs cannot fit. Because of this, the hard drive has to spin up frequently to read additional data.

In 2007 I noticed how newer versions of Rockbox left less free buffer space and I decided to make my own build with more free space. The first step was a RomBox build. This helped a lot, but I wasn't satisfied. I saved more RAM by disabling various features which I didn't need: code page loading, language loading and the voice interface. With this build, I have 1.774 MB of buffer space.

I also fixed a few bugs, either by backporting fixes from later versions or by fixing the bug myself. Most notably, I fixed the charging screen issues.

Here are some files associated with this custom build:
This is all based on Rockbox from November 2007. I've used this build for years on my V2 Recorder without running into any significant problems. I view it as a finished product, because I see no need to update the V2 Recorder to newer versions of Rockbox, and my attempts to minimize memory usage encountered diminishing returns.

I did not make any builds for other old Archos devices because I don't have access to those devices for testing. It should not be hard to build for those. The only tricky part is what I did to the language system to save RAM.

Update 

This is based on Rockbox r15545. You can now download just the patch. Here's a list of the included fixes and changes:
  • FS#9638 - temp_cue is unused and wasting memory 
  • FS#7631 - Charging screen broken on V2 Recorder. Several fixes enable the charging screen, display of input current on the screen, and proper startup from the charging screen.
  • FS#9635 - Instant backlight turn-off on FM/V2 Recorder
  • FS#8163 - Rockbox (Sansa) hangs in settings menu. This fixes a crash caused by the scrolling title used for setting text horizontal scrolling speed. 
  • Removal of language changing, with English language strings used directly from ROM. (This requires manual intervention when building.)
  • Removal of voice functionality.
  • Removal of codepage changing
  • Removal of the database (this is part of the RomBox instructions).
  • Removal of low battery shutdown
  • Unused conditionals for removing bookmark functionality. This part is probably incomplete and bookmark functionality remains.
In general, the removals are kind of incomplete and messy. I removed the main memory using parts, but I didn't remove all traces of those features. For example, the settings for removed features still remain. I did not extensively test all possibilities, but I did not run into any problems whatsoever over years of use.

Saturday, December 11, 2010

drop.io is closing and my files were hosted there

In the past I chose to use drop.io for hosting files (other than photos) which are associated with this blog. I just learned that drop.io is closing and all files will be deleted on December 15th. I just found out about this as I went there to replace a file with a newer version. The drop.io blog post claims that notification e-mails will be sent, but I didn't receive any e-mail despite having an e-mail address associated with my account.

I'm now hosting my files via Dropbox. I think I updated all the links. If you find a broken link, leave a blog comment here or on that particular article.

Wednesday, December 08, 2010

Sometimes, a period doesn't match any character

Recently I found that in regular expressions in GNU sed, ‘.’ failed to match some characters. At first it was very surprising, but there's a simple explanation in the GNU sed manual:
s/.*// does not clear pattern space
This happens if your input stream includes invalid multibyte sequences. POSIX mandates that such sequences are not matched by ‘.’, so that ‘s/.*//’ will not clear pattern space as you would expect. In fact, there is no way to clear sed's buffers in the middle of the script in most multibyte locales (including UTF-8 locales). For this reason, GNU sed provides a `z' command (for `zap') as an extension.

To work around these problems, which may cause bugs in shell scripts, set the LC_COLLATE and LC_CTYPE environment variables to ‘C’.

The used the ISO-8859-1 character set while Cygwin by default uses UTF-8. The characters not being matched formed invalid sequences in UTF-8. Setting ‘LANG=C’ also fixes the problem.

Thursday, December 02, 2010

Hiding a window from the Taskbar using WS_EX_TOOLWINDOW

A window can be hidden from the Taskbar by adding the WS_EX_TOOLWINDOW extended style. As a side-effect, this changes the window frame, but that may not be a problem. When modifying an already existing window, that window needs to be hidden and then showed again for the modification to take effect.

One application can easily do this to a window of another application. For example, here is a bit of code for doing this to Windows Live Messenger:
HWND hw = FindWindow("MSBLWindowClass", NULL);
if (hw == NULL) {
printf("Window not found.\n");
return -1;
}
ShowWindow(hw, SW_HIDE);
SetWindowLongPtr(hw, GWL_EXSTYLE,
GetWindowLongPtr(hw, GWL_EXSTYLE)
| WS_EX_TOOLWINDOW);
ShowWindow(hw, SW_SHOW);

It works well, but the code has to be run every time the window is created. It's better to actually create the window with WS_EX_TOOLWINDOW, but that requires a bit more work. The simplest way is to intercept the function which the application uses to create windows. Detours provides an easy way to do this. For example, to hide the Windows Live Messenger window, intercept CreateWindowExW. The intercepting function just needs to do the following before calling the real function:
if ((((DWORD)lpClassName) & ~0xFFFF) != 0 &&
!wcscmp(L"MSBLWindowClass", lpClassName)) {
dwExStyle |= WS_EX_TOOLWINDOW;
}

I don't recommend patching of binaries. It's more difficult to understand program flow and devise a patch, and some applications would make it even more difficult via packing and anti-debugger techniques. Patching also needs to be re-done when the application is updated. In this case, it only makes sense as a reverse engineering training exercise. One hint: a Win32 API monitoring program such as WinAPIOverride32 can easily find the location of the call.

Getting elapsed time since last Windows wakeup via CallNtPowerInformation

Windows provides the last system wake time via CallNtPowerInformation. It returns the "interrupt-time count, in 100-nanosecond units". To obtain the time since last wake, this needs to be subtracted from another value, but the documentation doesn't explain what other value can be used. In Windows 7, GetTickCount and GetTickCount64 (which return time in milliseconds) work great. The combination even returns a good result after a bootup, when the system hasn't slept yet. Do not use QueryUnbiasedInterruptTime or QueryPerformanceCounter. The latter will be close enough at first, but every time the system sleeps and wakes, additional error will accumulate.

Wednesday, November 10, 2010

Using Detours Express from GCC

Detours Express must be compiled using a Microsoft C++ compiler. It can be used from GCC, but some significant issues do come up.

When attempting to use Detours from GCC, the first problem is that GNU ld cannot resolve some symbols in static libraries that were created by Microsoft compilers. This can be solved by creating a DLL. First, a .def Module Definition File needs to be created to export the needed symbols. The list of functions can easily be obtained from the header file, using sed -n "s/^.* WINAPI \([^(]*\)(.*$/\1/p" detours.h. Once you have that, you just have to add a single data export and the statements that go at the beginning of the .def file:

..\detoured.lib msvcrt.lib kernel32.lib /out:detours.dll
LIBRARY detours
EXPORTS
DETOUR_EXE_RESTORE_GUID DATA


If you want, you can create a resource file with VERSIONINFO. Simply copy detours.rc in the Detours source directory and then edit it. The only fields that need to be edited are the FileDescription and DLL names. It's probably also a good idea to set the VS_FF_PRIVATEBUILD flag in FILEFLAGS by setting FILEFLAGS to 0x8L, and below provide a "PrivateBuild" VALUE with information about your build.

If you want to name your DLL detours.dll, it must not be built in the lib directory, because that would overwrite detours.lib, which is your input file. So, go to another directory and create the DLL:

set LIB=C:\WinDDK\7600.16385.1\lib\wxp\i386;C:\WinDDK\7600.16385.1\lib\Crt\i386
link /release /machine:x86 /dll /def:detours.def /incremental:no /subsystem:console detours.res ..\detours.lib ..\detoured.lib msvcrt.lib kernel32.lib /out:detours.dll


At this point, you have a usable DLL, but it's a good idea to create a corresponding .dll.a interface library file for GCC. This is a simple process, but a stdcall function decoration issue needs to be dealt with. The Detours Express API uses the stdcall calling convention, but the functions in the DLL have no decoration. (Windows system DLLs like kernel32.dll do the same thing.) It can be a problem, because GCC will attempt to link stdcall functions to decorated names such as DetourAttach@8. To solve this, create an entirely new .def file using gendef. Use the the -a switch, because gendef can't detect that zero-argument functions use stdcall, and do it in a new directory if you want to keep the old detours.def. DetourGetDetouredMarker forwards to Detoured in detoured.dll, so either run gendef on detoured.dll first or add the @0 to that name manually. Use dlltool to create the interface library, using the -k switch so the decorated names in the interface library can dynamically link with the undecorated exports in detours.dll:

dlltool -k -d detours.def -D detours.dll -l libdetours.a

Finally, everything is ready for compilation. The sample programs provide a simple way to test Detours Express, and with some minor changes, they can be compiled with g++. The main issue is that g++ follows the standard and refuses to automatically convert function pointers to void pointers, but that's easy to fix by adding (PVOID) casts.

Unfortunately, when using GNU ld from binutils 2.20.51.20100410, functions which are imported from DLLs are intercepted in the current module, bit not in any other modules. For example, the simple sample outputs that it "slept 0 ticks". This is because the thunk (which is an indirect jump to the actual function) is intercepted instead of the actual function. Detours attempts to correct this via DetourCodeFromPointer, but it fails because GNU ld doesn't fill out the data directory structure for the import address table and detour_is_imported returns false. (You can use objdump -p to view the data directory.) This bug was fixed in September 2010, and the binutils-2.21.51.tar.bz2 snapshot contains the fix. (Here is a thread discussing the fix and one CVS log entry from the fix.)

If you're using a buggy ld, it's also possible to work around this problem by declaring imported functions with __declspec(dllimport). When using the MinGW headers, Windows API functions may be declared this way by defining __W32API_USE_DLLIMPORT__ before including header files. This causes the corresponding function addresses to be correct, but no longer constant (due to dynamic linking). When compiling via g++, this is not a problem because the compiler automatically generates code to initialize global variables. However, gcc cannot do this and so code must be added to initialize such global variables at runtime.

Building Detours with the WDK compiler

Detours is a library for intercepting arbitrary Win32 binary functions. A free version called Detours Express is available "for research, non-commercial, and non-production use on 32-bit code".

The Detours Express package only contains source code. It must be compiled using Microsoft's C++ compiler because it uses non-standard extensions such as the try-except statement. I compiled it using the compiler in the WDK (Windows Driver Kit). (To install, download the WDK CD image and install "Build Environments". That list of packages requires 1.37 GB. If you want to reduce this, you can uninstall individual unwanted packages by right-clicking on their .msi files and selecting uninstall.)

Detours Express uses the DbgHelp library, but dbghelp.h is not in the WDK. This may be remedied by downloading Debugging Tools for Windows and installing the included SDK. (Detours Express loads dbghelp.dll via LoadLibraryA, so you don't have to worry about linking that in.)

By default, the compiler isn't in the path and there is no search path for include files or libraries. This may be remedied by setting some environment variables from a batch file:

PATH=C:\WinDDK\7600.16385.1\bin\x86;C:\WinDDK\7600.16385.1\bin\x86\x86;%PATH%
SET "INCLUDE=c:\WinDDK\7600.16385.1\inc\api;c:\WinDDK\7600.16385.1\inc\crt;C:\Program Files\Debugging Tools for Windows (x86)\sdk\inc"
SET LIB=C:\WinDDK\7600.16385.1\lib\wxp\i386


Recent versions of the WDK do not include lib.exe. This is not a problem, because lib simply called link. Simply replace lib with link /lib in the Makefile. After that, just run nmake and Detours will build.